* src/pic/device.c (register_map): fixed list construction
[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
44 extern symbol *interrupts[256];
45 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
46 extern int noAlloc;
47 extern set *publics;
48 extern set *externs;
49 extern unsigned maxInterrupts;
50 extern int maxRegBank;
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
75 char *udata_section_name=0;             // FIXME Temporary fix to change udata section name -- VR
76 int pic14_hasInterrupt = 0;             // Indicates whether to emit interrupt handler or not
77
78 static set *emitted = NULL;
79 int pic14_stringInSet(const char *str, set **world, int autoAdd);
80 static void emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize);
81
82 /*-----------------------------------------------------------------*/
83 /* aopLiteral - string from a literal value                        */
84 /*-----------------------------------------------------------------*/
85 unsigned int pic14aopLiteral (value *val, int offset)
86 {
87         union {
88                 float f;
89                 unsigned char c[4];
90         } fl;
91         
92         /* if it is a float then it gets tricky */
93         /* otherwise it is fairly simple */
94         if (!IS_FLOAT(val->type)) {
95                 unsigned long v = (unsigned long) floatFromVal(val);
96                 
97                 return ( (v >> (offset * 8)) & 0xff);
98         }
99         
100         /* it is type float */
101         fl.f = (float) floatFromVal(val);
102 #ifdef WORDS_BIGENDIAN
103         return fl.c[3-offset];
104 #else
105         return fl.c[offset];
106 #endif
107         
108 }
109
110 static int
111 is_valid_identifier( const char *name )
112 {
113   char a;
114   if (!name) return 0;
115   a = *name;
116   
117   /* only accept [a-zA-Z_][a-zA-Z0-9_] */
118   if (!((a >= 'a' && a <= 'z')
119         || (a >= 'A' && a <= 'z')
120         || (a == '_')))
121     return 0;
122
123   name++;
124   while ((a = *name++))
125   {
126     if (!((a >= 'a' && a <= 'z')
127         || (a >= 'A' && a <= 'Z')
128         || (a >= '0' && a <= '9')
129         || (a == '_')))
130       return 0;
131   } // while
132
133   /* valid identifier */
134   return 1;
135 }
136
137 #define IS_DEFINED_HERE(sym)    (!IS_EXTERN(sym->etype))
138 extern int IS_CONFIG_ADDRESS( int addr );
139 static void
140 pic14_constructAbsMap (struct dbuf_s *oBuf)
141 {
142   memmap *maps[] = { data, sfr, NULL };
143   int i;
144   hTab *ht = NULL;
145   symbol *sym;
146   set *aliases;
147   int addr, min=-1, max=-1;
148   int size;
149   PIC_device *pic;
150   int low, high, shared;
151
152   for (i=0; maps[i] != NULL; i++)
153   {
154     for (sym = (symbol *)setFirstItem (maps[i]->syms);
155         sym; sym = setNextItem (maps[i]->syms))
156     {
157       if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
158       {
159         addr = SPEC_ADDR(sym->etype);
160
161         /* handle CONFIG words here */
162         if (IS_CONFIG_ADDRESS( addr ))
163         {
164           //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
165           //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
166           if (sym->ival) {
167             pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
168           } else {
169             fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
170           }
171           continue;
172         }
173         
174         if (max == -1 || addr > max) max = addr;
175         if (min == -1 || addr < min) min = addr;
176         //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
177         aliases = hTabItemWithKey (ht, addr);
178         if (aliases) {
179           /* May not use addSetHead, as we cannot update the
180            * list's head in the hastable `ht'. */
181           addSet (&aliases, sym);
182 #if 0
183           fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
184               __FUNCTION__, elementsInSet(aliases), sym->name, addr);
185 #endif
186         } else {
187           addSet (&aliases, sym);
188           hTabAddItem (&ht, addr, aliases);
189         } // if
190       } // if
191     } // for sym
192   } // for i
193
194   /* now emit definitions for all absolute symbols */
195   dbuf_printf (oBuf, "%s", iComments2);
196   dbuf_printf (oBuf, "; absolute symbol definitions\n");
197   dbuf_printf (oBuf, "%s", iComments2);
198   for (addr=min; addr <= max; addr++)
199   {
200     size = 1;
201     aliases = hTabItemWithKey (ht, addr);
202     if (aliases && elementsInSet(aliases)) {
203       dbuf_printf (oBuf, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
204           moduleName, addr, addr);
205       for (sym = setFirstItem (aliases); sym;
206           sym = setNextItem (aliases))
207       {
208         /* emit STATUS as well as _STATUS, required for SFRs only */
209         dbuf_printf (oBuf, "\n%s", sym->name);
210         dbuf_printf (oBuf, "\n%s", sym->rname);
211         if (getSize(sym->type) > size) {
212           size = getSize(sym->type);
213         }
214         if (sym->islocal) {
215           // global symbols must be emitted again as 'global sym->name'
216           pic14_stringInSet(sym->name, &emitted, 1);
217           pic14_stringInSet(sym->rname, &emitted, 1);
218         }
219       } // for
220       dbuf_printf (oBuf, "\tres\t%d\n", size);
221     } // if
222   } // for i
223
224   /* also emit STK symbols
225    * XXX: This is ugly and fails as soon as devices start to get
226    *      differently sized sharebanks, since STK12 will be
227    *      required by larger devices but only up to STK03 might
228    *      be defined using smaller devices. */
229   dbuf_printf (oBuf, "\n");
230   shared = pic14_getSharedStack(&low, &high, &size);
231   if (!pic14_options.isLibrarySource)
232   {
233     pic = pic14_getPIC();
234
235     dbuf_printf (oBuf, "\tglobal PSAVE\n");
236     dbuf_printf (oBuf, "\tglobal SSAVE\n");
237     dbuf_printf (oBuf, "\tglobal WSAVE\n");
238     for (i = size - 4; i >= 0; i--) {
239       dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
240     } // for i
241
242     // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
243     // banks, sigh...
244     if (1 || !shared) {
245         // for single banked devices: use normal, "banked" RAM
246         dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
247     } else {
248         // for devices with at least two banks, require a sharebank section
249         dbuf_printf (oBuf, "sharebank udata_shr\n");
250     }
251     dbuf_printf (oBuf, "PSAVE\tres 1\n");
252     dbuf_printf (oBuf, "SSAVE\tres 1\n");
253     dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
254     /* fill rest of sharebank with stack STKxx .. STK00 */
255     for (i = size - 4; i >= 0; i--) {
256       dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
257     } // for i
258   } else {
259     /* declare STKxx as extern for all files
260      * except the one containing main() */
261     dbuf_printf (oBuf, "\textern PSAVE\n");
262     dbuf_printf (oBuf, "\textern SSAVE\n");
263     dbuf_printf (oBuf, "\textern WSAVE\n");
264     for (i = size - 4; i >= 0; i--) {
265         char buffer[128];
266         SNPRINTF(&buffer[0], 127, "STK%02d", i);
267         dbuf_printf (oBuf, "\textern %s\n", &buffer[0]);
268         pic14_stringInSet(&buffer[0], &emitted, 1);
269     } // for i
270   }
271 }
272
273 /*-----------------------------------------------------------------*/
274 /* emitRegularMap - emit code for maps with no special cases       */
275 /*-----------------------------------------------------------------*/
276 static void
277 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
278 {
279         symbol *sym;
280         int bitvars = 0;;
281         
282         /* print the area name */
283         if (addPublics)
284                 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
285         
286         for (sym = setFirstItem (map->syms); sym;
287         sym = setNextItem (map->syms)) {
288                 
289                 //printf("%s\n",sym->name);
290
291                 /* ignore if config word */
292                 if (SPEC_ABSA(sym->etype)
293                     && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
294                         continue;
295                 
296                 /* if extern then add it into the extern list */
297                 if (IS_EXTERN (sym->etype)) {
298                         addSetHead (&externs, sym);
299                         continue;
300                 }
301                 
302                 /* if allocation required check is needed
303                 then check if the symbol really requires
304                 allocation only for local variables */
305                 if (arFlag && !IS_AGGREGATE (sym->type) &&
306                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
307                         !sym->allocreq && sym->level)
308                         continue;
309                 
310                 /* if global variable & not static or extern
311                 and addPublics allowed then add it to the public set */
312                 if ((sym->level == 0 ||
313                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
314                         addPublics &&
315                         !IS_STATIC (sym->etype))
316                 {
317                         //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
318                         addSetHead (&publics, sym);
319                 }
320                 
321                 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
322                 if (sym->_isparm)
323                         continue;
324                         /* if extern then do nothing or is a function
325                 then do nothing */
326                 if (IS_FUNC (sym->type))
327                         continue;
328 #if 0
329                 /* print extra debug info if required */
330                 if (options.debug || sym->level == 0)
331                 {
332                         if (!sym->level)        /* global */
333                                 if (IS_STATIC (sym->etype))
334                                         dbuf_printf (&map->oBuf, "F%s_", moduleName);           /* scope is file */
335                                 else
336                                         dbuf_printf (&map->oBuf, "G_"); /* scope is global */
337                                 else
338                                         /* symbol is local */
339                                         dbuf_printf (&map->oBuf, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
340                                 dbuf_printf (&map->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
341                 }
342 #endif
343                 /* absolute symbols are handled in pic14_constructAbsMap */
344                 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
345                         continue;
346                 
347                 /* if it has an absolute address then generate
348                 an equate for this no need to allocate space */
349                 if (0 && SPEC_ABSA (sym->etype))
350                 {
351                         //if (options.debug || sym->level == 0)
352                         //dbuf_printf (&map->oBuf,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
353                         
354                         dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
355                                 sym->rname,
356                                 SPEC_ADDR (sym->etype));
357                 }
358                 else
359                 {
360                         /* allocate space */
361                         
362                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
363                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
364                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
365                         if (IS_BITVAR (sym->etype))
366                         {
367                                 bitvars++;
368                         }
369                         else
370                         {
371                                 emitSymbol (&map->oBuf,
372                                         sym->rname, 
373                                         NULL,
374                                         getSize (sym->type) & 0xffff,
375                                         SPEC_ABSA(sym->etype)
376                                                 ? SPEC_ADDR(sym->etype)
377                                                 : -1,
378                                         0,
379                                         0);
380                                 /*
381                                 {
382                                 int i, size;
383                                 
384                                   if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
385                                   {
386                                   for (i = 1; i < size; i++)
387                                   dbuf_printf (&map->oBuf, "\t%s_%d\n", sym->rname, i);
388                                   }
389                                   }
390                                 */
391                         }
392                         //dbuf_printf (&map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
393                 }
394                 
395                 /* if it has a initial value then do it only if
396                 it is a global variable */
397                 if (sym->ival && sym->level == 0) {
398                         ast *ival = NULL;
399                 
400                         if (IS_AGGREGATE (sym->type))
401                                 ival = initAggregates (sym, sym->ival, NULL);
402                         else
403                                 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
404                                 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
405                         codeOutBuf = &statsg->oBuf;
406                         GcurMemmap = statsg;
407                         eBBlockFromiCode (iCodeFromAst (ival));
408                         sym->ival = NULL;
409                 }
410         }
411 }
412
413
414 /*-----------------------------------------------------------------*/
415 /* printIvalType - generates ival for int/char                     */
416 /*-----------------------------------------------------------------*/
417 static void 
418 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
419 {
420         value *val;
421         unsigned long ulval;
422         
423         //fprintf(stderr, "%s\n",__FUNCTION__);
424         
425         /* if initList is deep */
426         if (ilist->type == INIT_DEEP)
427                 ilist = ilist->init.deep;
428         
429         if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
430                 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
431         }
432         
433         if (!(val = list2val (ilist))) {
434                 // assuming a warning has been thrown
435                 val=constVal("0");
436         }
437         
438         if (val->type != type) {
439                 val = valCastLiteral(type, floatFromVal(val));
440         }
441         
442         if(val) 
443                 ulval = (unsigned long) floatFromVal (val);
444         else
445                 ulval =0;
446         
447         switch (getSize (type)) {
448         case 1:
449                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
450                 break;
451                 
452         case 2:
453                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
454                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
455                 break;
456                 
457         case 4:
458                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
459                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
460                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
461                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
462                 break;
463         }
464 }
465
466 /*-----------------------------------------------------------------*/
467 /* printIvalBitFields - generate initializer for bitfields         */
468 /*-----------------------------------------------------------------*/
469 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb ) 
470 {
471         value *val ;
472         symbol *lsym = *sym;
473         initList *lilist = *ilist ;
474         unsigned long ival = 0;
475         int size =0;
476         
477         
478         do {
479                 unsigned long i;
480                 val = list2val(lilist);
481                 if (size) {
482                         if (SPEC_BLEN(lsym->etype) > 8) {
483                                 size += ((SPEC_BLEN (lsym->etype) / 8) + 
484                                         (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
485                         }
486                 } else {
487                         size = ((SPEC_BLEN (lsym->etype) / 8) + 
488                                 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
489                 }
490                 i = (unsigned long)floatFromVal(val);
491                 i <<= SPEC_BSTR (lsym->etype);
492                 ival |= i;
493                 if (! ( lsym->next &&
494                         (IS_BITFIELD(lsym->next->type)) &&
495                         (SPEC_BSTR(lsym->next->etype)))) break;
496                 lsym = lsym->next;
497                 lilist = lilist->next;
498         } while (1);
499         switch (size) {
500         case 1:
501                 //tfprintf (oFile, "\t!db !constbyte\n",ival);
502                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
503                 break;
504                 
505         case 2:
506                 //tfprintf (oFile, "\t!dw !constword\n",ival);
507                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
508                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
509                 break;
510         case 4:
511                 //tfprintf (oFile, "\t!db  !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
512                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
513                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
514                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
515                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
516                 break;
517         }
518         *sym = lsym;
519         *ilist = lilist;
520 }
521
522 /*-----------------------------------------------------------------*/
523 /* printIvalStruct - generates initial value for structures        */
524 /*-----------------------------------------------------------------*/
525 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
526 {
527         symbol *sflds;
528         initList *iloop = NULL;
529         
530         sflds = SPEC_STRUCT (type)->fields;
531         
532         if (ilist) {
533                 if (ilist->type != INIT_DEEP) {
534                         werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
535                         return;
536                 }
537                 
538                 iloop = ilist->init.deep;
539         }
540         
541         for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
542                 if (IS_BITFIELD(sflds->type)) {
543                         printIvalBitFields(&sflds,&iloop,pb);
544                 } else {
545                         printIval (sym, sflds->type, iloop, pb);
546                 }
547         }
548         if (iloop) {
549                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
550         }
551         return;
552 }
553
554 /*-----------------------------------------------------------------*/
555 /* printIvalChar - generates initital value for character array    */
556 /*-----------------------------------------------------------------*/
557 static int 
558 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
559 {
560         value *val;
561         int remain, ilen;
562         
563         if(!pb)
564                 return 0;
565         
566         //fprintf(stderr, "%s\n",__FUNCTION__);
567         if (!s)
568         {
569                 
570                 val = list2val (ilist);
571
572                 /* if the value is a character string  */
573                 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
574                 {
575                         ilen = DCL_ELEM(val->type);
576
577                         if (!DCL_ELEM (type))
578                                 DCL_ELEM (type) = ilen;
579                 
580                         /* emit string constant */
581                         for (remain = 0; remain < ilen; remain++) {
582                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
583                         }
584                         
585                         /* fill array up to desired size */
586                         if ((remain = (DCL_ELEM (type) - ilen)) > 0)
587                                 while (remain--)
588                                         //tfprintf (oFile, "\t!db !constbyte\n", 0);
589                                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
590                                 return 1;
591                 }
592                 else
593                         return 0;
594         }
595         else {
596                 //printChar (oFile, s, strlen (s) + 1);
597                 
598                 for(remain=0; remain<(int)strlen(s); remain++) {
599                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
600                         //fprintf(stderr,"0x%02x ",s[remain]);
601                 }
602                 //fprintf(stderr,"\n");
603         }
604         return 1;
605 }
606
607 /*-----------------------------------------------------------------*/
608 /* printIvalArray - generates code for array initialization        */
609 /*-----------------------------------------------------------------*/
610 static void 
611 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
612                                 pBlock *pb)
613 {
614         initList *iloop;
615         unsigned size = 0;
616
617         if(!pb)
618                 return;
619         if (ilist) {
620                 /* take care of the special   case  */
621                 /* array of characters can be init  */
622                 /* by a string                      */
623                 if (IS_CHAR (type->next)) {
624                         //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
625                         if (!IS_LITERAL(list2val(ilist)->etype)) {
626                                 werror (W_INIT_WRONG);
627                                 return;
628                         }
629                         if (printIvalChar (type,
630                                 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
631                                 pb, SPEC_CVAL (sym->etype).v_char))
632                                 return;
633                 }
634                 /* not the special case */
635                 if (ilist->type != INIT_DEEP) {
636                         werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
637                         return;
638                 }
639
640                 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
641                         if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
642                                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
643                                 break;
644                         }
645                         printIval (sym, type->next, iloop, pb);
646                 }
647         }
648
649         if (DCL_ELEM(type)) {
650                 // pad with zeros if needed
651                 if (size<DCL_ELEM(type)) {
652                         size = (DCL_ELEM(type) - size) * getSize(type->next);
653                         while (size--) {
654                                 //tfprintf (oFile, "\t!db !constbyte\n", 0);
655                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
656                         }
657                 }
658         } else {
659                 // we have not been given a size, but we now know it
660                 DCL_ELEM (type) = size;
661         }
662
663         return;
664 }
665
666 /*-----------------------------------------------------------------*/
667 /* printIvalPtr - generates code for initial value of pointers     */
668 /*-----------------------------------------------------------------*/
669 extern value *initPointer (initList *, sym_link *toType);
670
671 static void 
672 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
673 {
674         value *val;
675         
676         if (!ilist || !pb)
677                 return;
678         
679         fprintf (stderr, "FIXME: initializers for pointers...\n");
680         printTypeChain (type, stderr);
681         
682         fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
683         fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
684
685         if (ilist && (ilist->type == INIT_DEEP))
686           ilist = ilist->init.deep;
687         
688         /* function pointers */
689         if (IS_FUNC (type->next))
690         {
691                 assert ( !"function pointers not yet handled" );
692                 //printIvalFuncPtr (type, ilist, pb);
693         }
694
695         if (!(val = initPointer (ilist, type)))
696                 return;
697         
698         if (IS_CHAR (type->next))
699         {
700                 if (printIvalChar (type, ilist, pb, NULL)) return;
701         }
702
703         /* check the type */
704         if (compareType (type, val->type) == 0)
705         {
706                 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
707                 printFromToType (val->type, type);
708         }
709
710         if (IS_LITERAL (val->etype))
711         {
712                 switch (getSize (type))
713                 {
714                 case 1:
715                         fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
716                         break;
717                 case 2:
718                         fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
719                         break;
720                 case 3: /* gneric pointers */
721                         assert ( !"generic pointers not yet handled" );
722                 case 4:
723                         fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
724                         break;
725                 default:
726                         assert ( !"invaild size of value -- aborting" );
727                 } // switch
728
729                 return;
730         } // if (IS_LITERAL)
731
732         /* now handle symbolic values */
733         switch (getSize (type))
734         {
735         case 1:
736                 fprintf (stderr, "BYTE: %s", val->name);
737                 break;
738         case 2:
739                 fprintf (stderr, "WORD: %s", val->name);
740                 break;
741         case 4:
742                 fprintf (stderr, "LONG: %s", val->name);
743                 break;
744         default:
745                 assert ( !"invalid size of (symbolic) value -- aborting" );
746         } // switch
747 }
748
749 /*-----------------------------------------------------------------*/
750 /* printIval - generates code for initial value                    */
751 /*-----------------------------------------------------------------*/
752 static void 
753 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
754 {
755         if (!ilist || !pb)
756                 return;
757         
758         /* if structure then    */
759         if (IS_STRUCT (type))
760         {
761                 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
762                 printIvalStruct (sym, type, ilist, pb);
763                 return;
764         }
765         
766         /* if this is an array   */
767         if (IS_ARRAY (type))
768         {
769                 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
770                 printIvalArray (sym, type, ilist, pb);
771                 return;
772         }
773         
774         /* if this is a pointer */
775         if (IS_PTR (type))
776         {
777                 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
778                 printIvalPtr (sym, type, ilist, pb);
779                 return;
780         }
781         
782         /* if type is SPECIFIER */
783         if (IS_SPEC (type))
784         {
785                 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
786                 printIvalType (sym, type, ilist, pb);
787                 return;
788         }
789 }
790
791 extern void pCodeConstString(char *name, char *value);
792 /*-----------------------------------------------------------------*/
793 /* emitStaticSeg - emitcode for the static segment                 */
794 /*-----------------------------------------------------------------*/
795 static void
796 pic14emitStaticSeg (memmap * map)
797 {
798         symbol *sym;
799         
800         dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
801         
802         //fprintf(stderr, "%s\n",__FUNCTION__);
803         
804         /* for all variables in this segment do */
805         for (sym = setFirstItem (map->syms); sym;
806         sym = setNextItem (map->syms))
807         {
808                 /* if extern then add it into the extern list */
809                 if (IS_EXTERN (sym->etype)) {
810                         addSetHead (&externs, sym);
811                         continue;
812                 }
813                 
814                 /* if it is not static add it to the public
815                 table */
816                 if (!IS_STATIC (sym->etype))
817                         addSetHead (&publics, sym);
818                 
819                 /* print extra debug info if required */
820                 if (options.debug || sym->level == 0)
821                 {
822                         if (!sym->level)
823                         {                       /* global */
824                                 if (IS_STATIC (sym->etype))
825                                         dbuf_printf (&code->oBuf, "F%s_", moduleName);  /* scope is file */
826                                 else
827                                         dbuf_printf (&code->oBuf, "G_");        /* scope is global */
828                         }
829                         else
830                                 /* symbol is local */
831                                 dbuf_printf (&code->oBuf, "L%s_",
832                                 (sym->localof ? sym->localof->name : "-null-"));
833                         dbuf_printf (&code->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
834                         
835                 }
836                 
837                 /* if it has an absolute address */
838                 if (SPEC_ABSA (sym->etype))
839                 {
840                         if (options.debug || sym->level == 0)
841                                 dbuf_printf (&code->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
842                         
843                         dbuf_printf (&code->oBuf, "%s\t=\t0x%04x\n",
844                                 sym->rname,
845                                 SPEC_ADDR (sym->etype));
846                 }
847                 else
848                 {
849                         if (options.debug || sym->level == 0)
850                                 dbuf_printf (&code->oBuf, " == .\n");
851                         
852                         /* if it has an initial value */
853                         if (sym->ival)
854                         {
855                                 pBlock *pb;
856                                 
857                                 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
858                                 noAlloc++;
859                                 resolveIvalSym (sym->ival, sym->type);
860                                 //printIval (sym, sym->type, sym->ival, &code->oBuf);
861                                 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
862                                 addpBlock(pb);
863                                 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
864                                 
865                                 printIval (sym, sym->type, sym->ival, pb);
866                                 noAlloc--;
867                         }
868                         else
869                         {
870                                 
871                                 /* allocate space */
872                                 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
873                                 /* special case for character strings */
874                                 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
875                                         SPEC_CVAL (sym->etype).v_char)
876                                         pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
877                                         /*printChar (code->oFile,
878                                         SPEC_CVAL (sym->etype).v_char,
879                                 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
880                                 else
881                                         dbuf_printf (&code->oBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
882                         }
883                 }
884         }
885         
886 }
887
888
889 /*-----------------------------------------------------------------*/
890 /* emitMaps - emits the code for the data portion the code         */
891 /*-----------------------------------------------------------------*/
892 static void
893 pic14emitMaps ()
894 {
895         pic14_constructAbsMap (&sfr->oBuf);
896 /* no special considerations for the following
897         data, idata & bit & xdata */
898         pic14emitRegularMap (data, TRUE, TRUE);
899         pic14emitRegularMap (idata, TRUE, TRUE);
900         pic14emitRegularMap (bit, TRUE, FALSE);
901         pic14emitRegularMap (xdata, TRUE, TRUE);
902         pic14emitRegularMap (sfr, TRUE, FALSE);
903         pic14emitRegularMap (sfrbit, FALSE, FALSE);
904         pic14emitRegularMap (code, TRUE, FALSE);
905         pic14emitStaticSeg (statsg);
906         pic14emitStaticSeg (c_abs);
907 }
908
909 /*-----------------------------------------------------------------*/
910 /* createInterruptVect - creates the interrupt vector              */
911 /*-----------------------------------------------------------------*/
912 static void
913 pic14createInterruptVect (struct dbuf_s * vBuf)
914 {
915         mainf = newSymbol ("main", 0);
916         mainf->block = 0;
917         
918         /* only if the main function exists */
919         if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
920         {
921                 struct options *op = &options;
922                 if (!(op->cc_only || noAssemble))
923                         //      werror (E_NO_MAIN);
924                         fprintf(stderr,"WARNING: function 'main' undefined\n");
925                 return;
926         }
927         
928         /* if the main is only a prototype ie. no body then do nothing */
929         if (!IFFUNC_HASBODY(mainf->type))
930         {
931                 /* if ! compile only then main function should be present */
932                 if (!(options.cc_only || noAssemble))
933                         //      werror (E_NO_MAIN);
934                         fprintf(stderr,"WARNING: function 'main' undefined\n");
935                 return;
936         }
937         
938         dbuf_printf (vBuf, "%s", iComments2);
939         dbuf_printf (vBuf, "; reset vector \n");
940         dbuf_printf (vBuf, "%s", iComments2);
941         dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
942         dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
943         dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
944         dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
945 }
946
947
948 /*-----------------------------------------------------------------*/
949 /* initialComments - puts in some initial comments                 */
950 /*-----------------------------------------------------------------*/
951 static void
952 pic14initialComments (FILE * afile)
953 {
954         initialComments (afile);
955         fprintf (afile, "; PIC port for the 14-bit core\n");
956         fprintf (afile, iComments2);
957         
958 }
959
960 int
961 pic14_stringInSet(const char *str, set **world, int autoAdd)
962 {
963   char *s;
964
965   if (!str) return 1;
966   assert(world);
967
968   for (s = setFirstItem(*world); s; s = setNextItem(*world))
969   {
970     /* found in set */
971     if (0 == strcmp(s, str)) return 1;
972   }
973
974   /* not found */
975   if (autoAdd) addSet(world, Safe_strdup(str));
976   return 0;
977 }
978
979 static int
980 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
981 {
982   if (!pic14_stringInSet(sym, &emitted, 1)) {
983     /* sym was not in emittedSymbols */
984     if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
985       /* sym is not a locally defined function---avoid bug #1443651 */
986       fprintf( file, fmt, sym );
987       return 0;
988     }
989   }
990   return 1;
991 }
992
993 /*-------------------------------------------------------------------*/
994 /* emitSymbol - write a symbol definition only if it is not    */
995 /*                    already present                                */
996 /*-------------------------------------------------------------------*/
997
998 static void
999 emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1000 {
1001     static unsigned int sec_idx = 0;
1002
1003     /* workaround: variables declared via `sbit' result in a numeric
1004      * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1005      * sbit is heavily used in the inc2h-generated header files!
1006      */
1007     if (!is_valid_identifier(name))
1008     {
1009         //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1010         return;
1011     }
1012
1013     /* check whether the symbol is already defined */
1014     if (pic14_stringInSet(name, &emitted, 1)) return;
1015
1016     /* new symbol -- define it */
1017     //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1018     if (useEQU) {
1019         dbuf_printf (oBuf, "%s\tEQU\t0x%04x\n", name, addr);
1020     } else {
1021         /* we place each symbol into a section of its own to allow the linker
1022          * to distribute the data into all available memory banks */
1023         if (!section_type) section_type = "udata";
1024         if (addr != -1)
1025         {
1026             /* absolute symbols are handled in pic14_constructAbsMap */
1027             /* do nothing */
1028         } else {
1029             if (globalize) dbuf_printf (oBuf, "\tglobal\t%s\n", name);
1030             dbuf_printf (oBuf, "udata_%s_%u\t%s\n", moduleName,
1031                     sec_idx++, section_type);
1032             dbuf_printf (oBuf, "%s\tres\t%d\n", name, size);
1033         }
1034     }
1035 }
1036
1037 /*-----------------------------------------------------------------*/
1038 /* printExterns - generates extern for external variables          */
1039 /*-----------------------------------------------------------------*/
1040 static void
1041 pic14printExterns (FILE * afile)
1042 {
1043         symbol *sym;
1044         
1045         fprintf (afile, "%s", iComments2);
1046         fprintf (afile, "; extern variables in this module\n");
1047         fprintf (afile, "%s", iComments2);
1048         
1049         for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1050                 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1051 }
1052
1053 /*-----------------------------------------------------------------*/
1054 /* printPublics - generates .global for publics                    */
1055 /*-----------------------------------------------------------------*/
1056 static void
1057 pic14printPublics (FILE * afile)
1058 {
1059   symbol *sym;
1060
1061   fprintf (afile, "%s", iComments2);
1062   fprintf (afile, "; public variables in this module\n");
1063   fprintf (afile, "%s", iComments2);
1064
1065   for (sym = setFirstItem (publics); sym;
1066       sym = setNextItem (publics)) {
1067
1068     if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1069       if (!IS_BITVAR(sym->type))
1070         pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1071     } else {
1072       /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1073       /* Not any longer! */
1074       //if (!SPEC_ABSA (sym->etype))
1075       pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1076     }
1077   }
1078 }
1079
1080 static void
1081 pic14printLocals (FILE * afile)
1082 {
1083   set *allregs[6] = { dynAllocRegs, dynStackRegs, dynProcessorRegs, dynDirectRegs, dynDirectBitRegs, dynInternalRegs };
1084   regs *reg;
1085   int i;
1086   struct dbuf_s dbuf;
1087
1088   dbuf_init(&dbuf, 1024);
1089   /* emit all registers from all possible sets */
1090   for (i = 0; i < 6; i++) {
1091     if (allregs[i] == NULL) continue;
1092
1093     for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1094       if (reg->isEmitted) continue;
1095
1096       if (reg->wasUsed && !reg->isExtern) {
1097         emitSymbol(&dbuf, reg->name, "udata", reg->size, reg->isFixed ? reg->address : -1, 0, reg->isPublic);
1098       }
1099       reg->isEmitted = 1;
1100     } // for
1101   } // for
1102   dbuf_write_and_destroy(&dbuf, afile);
1103 }
1104
1105 /*-----------------------------------------------------------------*/
1106 /* emitOverlay - will emit code for the overlay stuff              */
1107 /*-----------------------------------------------------------------*/
1108 static void
1109 pic14emitOverlay (struct dbuf_s * aBuf)
1110 {
1111         set *ovrset;
1112         
1113         /*  if (!elementsInSet (ovrSetSets))*/
1114         
1115         /* the hack below, fixes translates for devices which
1116         * only have udata_shr memory */
1117         dbuf_printf (aBuf, "%s\t%s\n",
1118                 (elementsInSet(ovrSetSets)?"":";"),
1119                 port->mem.overlay_name);
1120         
1121         /* for each of the sets in the overlay segment do */
1122         for (ovrset = setFirstItem (ovrSetSets); ovrset;
1123         ovrset = setNextItem (ovrSetSets))
1124         {
1125                 
1126                 symbol *sym;
1127                 
1128                 if (elementsInSet (ovrset))
1129                 {
1130                 /* this dummy area is used to fool the assembler
1131                 otherwise the assembler will append each of these
1132                 declarations into one chunk and will not overlay
1133                         sad but true */
1134                         
1135                         /* I don't think this applies to us. We are using gpasm.  CRF */
1136                         
1137                         dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1138                         /* output the area informtion */
1139                         dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);   /* MOF */
1140                 }
1141                 
1142                 for (sym = setFirstItem (ovrset); sym;
1143                 sym = setNextItem (ovrset))
1144                 {
1145                         
1146                         /* if extern then do nothing */
1147                         if (IS_EXTERN (sym->etype))
1148                                 continue;
1149                         
1150                                 /* if allocation required check is needed
1151                                 then check if the symbol really requires
1152                         allocation only for local variables */
1153                         if (!IS_AGGREGATE (sym->type) &&
1154                                 !(sym->_isparm && !IS_REGPARM (sym->etype))
1155                                 && !sym->allocreq && sym->level)
1156                                 continue;
1157                         
1158                                 /* if global variable & not static or extern
1159                         and addPublics allowed then add it to the public set */
1160                         if ((sym->_isparm && !IS_REGPARM (sym->etype))
1161                                 && !IS_STATIC (sym->etype))
1162                                 addSetHead (&publics, sym);
1163                         
1164                                 /* if extern then do nothing or is a function
1165                         then do nothing */
1166                         if (IS_FUNC (sym->type))
1167                                 continue;
1168                         
1169                         /* print extra debug info if required */
1170                         if (options.debug || sym->level == 0)
1171                         {
1172                                 if (!sym->level)
1173                                 {               /* global */
1174                                         if (IS_STATIC (sym->etype))
1175                                                 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1176                                         else
1177                                                 dbuf_printf (aBuf, "G_");       /* scope is global */
1178                                 }
1179                                 else
1180                                         /* symbol is local */
1181                                         dbuf_printf (aBuf, "L%s_",
1182                                         (sym->localof ? sym->localof->name : "-null-"));
1183                                 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1184                         }
1185                         
1186                         /* if is has an absolute address then generate
1187                         an equate for this no need to allocate space */
1188                         if (SPEC_ABSA (sym->etype))
1189                         {
1190                                 
1191                                 if (options.debug || sym->level == 0)
1192                                         dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1193                                 
1194                                 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1195                                         sym->rname,
1196                                         SPEC_ADDR (sym->etype));
1197                         }
1198                         else
1199                         {
1200                                 if (options.debug || sym->level == 0)
1201                                         dbuf_printf (aBuf, "==.\n");
1202                                 
1203                                 /* allocate space */
1204                                 dbuf_printf (aBuf, "%s:\n", sym->rname);
1205                                 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1206                         }
1207                         
1208                 }
1209         }
1210 }
1211
1212
1213 void
1214 pic14_emitInterruptHandler (FILE * asmFile)
1215 {
1216         if (pic14_hasInterrupt)
1217         {
1218
1219                 fprintf (asmFile, "%s", iComments2);
1220                 fprintf (asmFile, "; interrupt and initialization code\n");
1221                 fprintf (asmFile, "%s", iComments2);
1222                 // Note - for mplink may have to enlarge section vectors in .lnk file
1223                 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1224                 //       source files's code segment (interrupt.c -> code_interrupt)
1225                 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1226                 
1227                 /* interrupt service routine */
1228                 fprintf (asmFile, "__sdcc_interrupt\n");
1229                 copypCode(asmFile, 'I');
1230         }       
1231 }
1232
1233 /*-----------------------------------------------------------------*/
1234 /* glue - the final glue that hold the whole thing together        */
1235 /*-----------------------------------------------------------------*/
1236 void
1237 picglue ()
1238 {
1239         char udata_name[80];
1240         FILE *asmFile;
1241         struct dbuf_s ovrBuf;
1242         struct dbuf_s vBuf;
1243
1244         dbuf_init(&ovrBuf, 4096);
1245         dbuf_init(&vBuf, 4096);
1246
1247         pCodeInitRegisters();
1248
1249         /* check for main() */
1250         mainf = newSymbol ("main", 0);
1251         mainf->block = 0;
1252         mainf = findSymWithLevel (SymbolTab, mainf);
1253
1254         if (!mainf || !IFFUNC_HASBODY(mainf->type))
1255         {
1256                 /* main missing -- import stack from main module */
1257                 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1258                 pic14_options.isLibrarySource = 1;
1259         }
1260
1261 #if 0
1262         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1263                 
1264                 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1265                 addpBlock(pb);
1266                 
1267                 /* entry point @ start of CSEG */
1268                 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1269                 /* put in the call to main */
1270                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1271                 
1272                 if (options.mainreturn) {
1273                         
1274                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1275                         addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1276                         
1277                 } else {
1278                         
1279                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1280                         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1281                         
1282                 }
1283         }
1284 #endif  
1285         
1286         /* At this point we've got all the code in the form of pCode structures */
1287         /* Now it needs to be rearranged into the order it should be placed in the */
1288         /* code space */
1289         
1290         movepBlock2Head('P');              // Last
1291         movepBlock2Head(code->dbName);
1292         movepBlock2Head('X');
1293         movepBlock2Head(statsg->dbName);   // First
1294         
1295         
1296         /* print the global struct definitions */
1297         if (options.debug)
1298                 cdbStructBlock (0);
1299         
1300         /* emit code for the all the variables declared */
1301         pic14emitMaps ();
1302         /* do the overlay segments */
1303         pic14emitOverlay(&ovrBuf);
1304         
1305         /* PENDING: this isnt the best place but it will do */
1306         if (port->general.glue_up_main) {
1307                 /* create the interrupt vector table */
1308                 pic14createInterruptVect (&vBuf);
1309         }
1310         
1311         AnalyzepCode('*');
1312         
1313         ReuseReg(); // ReuseReg where call tree permits
1314         
1315         InlinepCode();
1316         
1317         AnalyzepCode('*');
1318         
1319         pcode_test();
1320         
1321         
1322         /* now put it all together into the assembler file */
1323         /* create the assembler file name */
1324         
1325         if ((noAssemble || options.c1mode) && fullDstFileName)
1326         {
1327                 sprintf (buffer, fullDstFileName);
1328         }
1329         else
1330         {
1331                 sprintf (buffer, dstFileName);
1332                 strcat (buffer, ".asm");
1333         }
1334         
1335         if (!(asmFile = fopen (buffer, "w"))) {
1336                 werror (E_FILE_OPEN_ERR, buffer);
1337                 exit (1);
1338         }
1339
1340         /* prepare statistics */
1341         resetpCodeStatistics ();
1342         
1343         /* initial comments */
1344         pic14initialComments (asmFile);
1345         
1346         /* print module name */
1347         fprintf (asmFile, ";\t.module %s\n", moduleName);
1348         
1349         /* Let the port generate any global directives, etc. */
1350         if (port->genAssemblerPreamble)
1351         {
1352                 port->genAssemblerPreamble(asmFile);
1353         }
1354
1355         /* Emit the __config directive */
1356         pic14_emitConfigWord (asmFile);
1357         
1358         /* print the global variables in this module */
1359         pic14printPublics (asmFile);
1360         
1361         /* print the extern variables in this module */
1362         pic14printExterns (asmFile);
1363         
1364         /* copy the sfr segment */
1365         fprintf (asmFile, "%s", iComments2);
1366         fprintf (asmFile, "; special function registers\n");
1367         fprintf (asmFile, "%s", iComments2);
1368         dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1369         
1370         
1371         if (udata_section_name) {
1372                 sprintf(udata_name,"%s",udata_section_name);
1373         } else {
1374                 sprintf(udata_name,"data_%s",moduleName);
1375         }
1376         fprintf (asmFile, "%s", iComments2);
1377         fprintf (asmFile, "; udata\n");
1378         fprintf (asmFile, "%s", iComments2);
1379         fprintf (asmFile, "%s\tudata\n", udata_name);
1380         dbuf_write_and_destroy(&data->oBuf, asmFile);
1381         
1382         /* Put all variables into a cblock */
1383         AnalyzeBanking();
1384
1385         /* print the locally defined variables in this module */
1386         writeUsedRegs(asmFile);
1387         pic14printLocals (asmFile);
1388         
1389         /* create the overlay segments */
1390         fprintf (asmFile, "%s", iComments2);
1391         fprintf (asmFile, "; overlayable items in internal ram \n");
1392         fprintf (asmFile, "%s", iComments2);    
1393         dbuf_write_and_destroy (&ovrBuf, asmFile);
1394         
1395 #if 0
1396         
1397         /* create the stack segment MOF */
1398         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1399                 fprintf (asmFile, "%s", iComments2);
1400                 fprintf (asmFile, "; Stack segment in internal ram \n");
1401                 fprintf (asmFile, "%s", iComments2);    
1402                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1403                         ";__start__stack:\n;\t.ds\t1\n\n");
1404         }
1405         
1406         /* create the idata segment */
1407         fprintf (asmFile, "%s", iComments2);
1408         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1409         fprintf (asmFile, "%s", iComments2);
1410         dbuf_write_and_destroy (&idata->oBuf, asmFile);
1411
1412         /* if external stack then reserve space of it */
1413         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1414                 fprintf (asmFile, "%s", iComments2);
1415                 fprintf (asmFile, "; external stack \n");
1416                 fprintf (asmFile, "%s", iComments2);
1417                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1418                 fprintf (asmFile,";\t.ds 256\n");
1419         }
1420         
1421         /* copy xtern ram data */
1422         fprintf (asmFile, "%s", iComments2);
1423         fprintf (asmFile, "; external ram data\n");
1424         fprintf (asmFile, "%s", iComments2);
1425         dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1426
1427 #endif
1428         
1429         /* copy the bit segment */
1430         fprintf (asmFile, "%s", iComments2);
1431         fprintf (asmFile, "; bit data\n");
1432         fprintf (asmFile, "%s", iComments2);
1433         dbuf_write_and_destroy (&bit->oBuf, asmFile);
1434
1435         /* copy the interrupt vector table */
1436         if (mainf && IFFUNC_HASBODY(mainf->type))
1437           dbuf_write_and_destroy (&vBuf, asmFile);
1438         else
1439           dbuf_destroy(&vBuf);
1440
1441         /* create interupt ventor handler */
1442         pic14_emitInterruptHandler (asmFile);
1443         
1444         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1445                 /* initialize data memory */
1446                 /* do NOT name this code_init to avoid conflicts with init.c */
1447                 fprintf (asmFile, "c_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1448                 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1449                 /* FIXME: This is temporary.  The idata section should be used.  If 
1450                 not, we could add a special feature to the linker.  This will 
1451                 work in the mean time.  Put all initalized data in main.c */
1452                 copypCode(asmFile, statsg->dbName);
1453                 fprintf (asmFile,"\tpagesel _main\n");
1454                 fprintf (asmFile,"\tgoto _main\n");
1455         }
1456         
1457 #if 0    
1458         
1459         /* copy global & static initialisations */
1460         fprintf (asmFile, "%s", iComments2);
1461         fprintf (asmFile, "; global & static initialisations\n");
1462         fprintf (asmFile, "%s", iComments2);
1463         copypCode(asmFile, statsg->dbName);
1464         
1465 #endif
1466         
1467         /* copy over code */
1468         fprintf (asmFile, "%s", iComments2);
1469         fprintf (asmFile, "; code\n");
1470         fprintf (asmFile, "%s", iComments2);
1471         fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1472         
1473         /* unknown */
1474         copypCode(asmFile, 'X');
1475         
1476         /* _main function */
1477         copypCode(asmFile, 'M');
1478         
1479         /* other functions */
1480         copypCode(asmFile, code->dbName);
1481         
1482         /* unknown */
1483         copypCode(asmFile, 'P');
1484
1485         dumppCodeStatistics (asmFile);
1486         
1487         fprintf (asmFile,"\tend\n");
1488         
1489         fclose (asmFile);
1490 }