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