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