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