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