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