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