* src/pic/glue.h,src/pic16/glue.h: added prototypes
[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, "\tgoto\t__sdcc_gsinit_startup\n");
1014 }
1015
1016
1017 /*-----------------------------------------------------------------*/
1018 /* initialComments - puts in some initial comments                 */
1019 /*-----------------------------------------------------------------*/
1020 static void
1021 pic14initialComments (FILE * afile)
1022 {
1023         initialComments (afile);
1024         fprintf (afile, "; PIC port for the 14-bit core\n");
1025         fprintf (afile, iComments2);
1026         
1027 }
1028
1029 int
1030 pic14_stringInSet(const char *str, set **world, int autoAdd)
1031 {
1032   char *s;
1033
1034   if (!str) return 1;
1035   assert(world);
1036
1037   for (s = setFirstItem(*world); s; s = setNextItem(*world))
1038   {
1039     /* found in set */
1040     if (0 == strcmp(s, str)) return 1;
1041   }
1042
1043   /* not found */
1044   if (autoAdd) addSet(world, Safe_strdup(str));
1045   return 0;
1046 }
1047
1048 static int
1049 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1050 {
1051   static set *emitted = NULL;
1052
1053   if (!pic14_stringInSet(sym, &emitted, 1)) {
1054     /* sym was not in emittedSymbols */
1055     if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1056       /* sym is not a locally defined function---avoid bug #1443651 */
1057       fprintf( file, fmt, sym );
1058       return 0;
1059     }
1060   }
1061   return 1;
1062 }
1063
1064 /*-----------------------------------------------------------------*/
1065 /* printExterns - generates extern for external variables          */
1066 /*-----------------------------------------------------------------*/
1067 static void
1068 pic14printExterns (FILE * afile)
1069 {
1070         symbol *sym;
1071         
1072         fprintf (afile, "%s", iComments2);
1073         fprintf (afile, "; extern variables in this module\n");
1074         fprintf (afile, "%s", iComments2);
1075         
1076         for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1077                 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1078 }
1079
1080 /*-----------------------------------------------------------------*/
1081 /* printPublics - generates .global for publics                    */
1082 /*-----------------------------------------------------------------*/
1083 static void
1084 pic14printPublics (FILE * afile)
1085 {
1086   symbol *sym;
1087
1088   fprintf (afile, "%s", iComments2);
1089   fprintf (afile, "; publics variables in this module\n");
1090   fprintf (afile, "%s", iComments2);
1091
1092   for (sym = setFirstItem (publics); sym;
1093       sym = setNextItem (publics)) {
1094
1095     if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1096       if (!IS_BITVAR(sym->type))
1097         pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1098     } else {
1099       /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1100       /* Not any longer! */
1101       //if (!SPEC_ABSA (sym->etype))
1102       pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1103     }
1104   }
1105 }
1106
1107 /*-----------------------------------------------------------------*/
1108 /* emitOverlay - will emit code for the overlay stuff              */
1109 /*-----------------------------------------------------------------*/
1110 static void
1111 pic14emitOverlay (FILE * afile)
1112 {
1113         set *ovrset;
1114         
1115         /*  if (!elementsInSet (ovrSetSets))*/
1116         
1117         /* the hack below, fixes translates for devices which
1118         * only have udata_shr memory */
1119         fprintf (afile, "%s\t%s\n",
1120                 (elementsInSet(ovrSetSets)?"":";"),
1121                 port->mem.overlay_name);
1122         
1123         /* for each of the sets in the overlay segment do */
1124         for (ovrset = setFirstItem (ovrSetSets); ovrset;
1125         ovrset = setNextItem (ovrSetSets))
1126         {
1127                 
1128                 symbol *sym;
1129                 
1130                 if (elementsInSet (ovrset))
1131                 {
1132                 /* this dummy area is used to fool the assembler
1133                 otherwise the assembler will append each of these
1134                 declarations into one chunk and will not overlay
1135                         sad but true */
1136                         
1137                         /* I don't think this applies to us. We are using gpasm.  CRF */
1138                         
1139                         fprintf (afile, ";\t.area _DUMMY\n");
1140                         /* output the area informtion */
1141                         fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);      /* MOF */
1142                 }
1143                 
1144                 for (sym = setFirstItem (ovrset); sym;
1145                 sym = setNextItem (ovrset))
1146                 {
1147                         
1148                         /* if extern then do nothing */
1149                         if (IS_EXTERN (sym->etype))
1150                                 continue;
1151                         
1152                                 /* if allocation required check is needed
1153                                 then check if the symbol really requires
1154                         allocation only for local variables */
1155                         if (!IS_AGGREGATE (sym->type) &&
1156                                 !(sym->_isparm && !IS_REGPARM (sym->etype))
1157                                 && !sym->allocreq && sym->level)
1158                                 continue;
1159                         
1160                                 /* if global variable & not static or extern
1161                         and addPublics allowed then add it to the public set */
1162                         if ((sym->_isparm && !IS_REGPARM (sym->etype))
1163                                 && !IS_STATIC (sym->etype))
1164                                 addSetHead (&publics, sym);
1165                         
1166                                 /* if extern then do nothing or is a function
1167                         then do nothing */
1168                         if (IS_FUNC (sym->type))
1169                                 continue;
1170                         
1171                         /* print extra debug info if required */
1172                         if (options.debug || sym->level == 0)
1173                         {
1174                                 if (!sym->level)
1175                                 {               /* global */
1176                                         if (IS_STATIC (sym->etype))
1177                                                 fprintf (afile, "F%s_", moduleName);    /* scope is file */
1178                                         else
1179                                                 fprintf (afile, "G_");  /* scope is global */
1180                                 }
1181                                 else
1182                                         /* symbol is local */
1183                                         fprintf (afile, "L%s_",
1184                                         (sym->localof ? sym->localof->name : "-null-"));
1185                                 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1186                         }
1187                         
1188                         /* if is has an absolute address then generate
1189                         an equate for this no need to allocate space */
1190                         if (SPEC_ABSA (sym->etype))
1191                         {
1192                                 
1193                                 if (options.debug || sym->level == 0)
1194                                         fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1195                                 
1196                                 fprintf (afile, "%s\t=\t0x%04x\n",
1197                                         sym->rname,
1198                                         SPEC_ADDR (sym->etype));
1199                         }
1200                         else
1201                         {
1202                                 if (options.debug || sym->level == 0)
1203                                         fprintf (afile, "==.\n");
1204                                 
1205                                 /* allocate space */
1206                                 fprintf (afile, "%s:\n", sym->rname);
1207                                 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1208                         }
1209                         
1210                 }
1211         }
1212 }
1213
1214
1215 void
1216 pic14_emitInterruptHandler (FILE * asmFile)
1217 {
1218         if (pic14_hasInterrupt)
1219         {
1220
1221                 fprintf (asmFile, "%s", iComments2);
1222                 fprintf (asmFile, "; interrupt and initialization code\n");
1223                 fprintf (asmFile, "%s", iComments2);
1224                 // Note - for mplink may have to enlarge section vectors in .lnk file
1225                 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1226                 //       source files's code segment (interrupt.c -> code_interrupt)
1227                 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1228                 
1229                 /* interrupt service routine */
1230                 fprintf (asmFile, "__sdcc_interrupt\n");
1231                 copypCode(asmFile, 'I');
1232         }       
1233 }
1234
1235 /*-----------------------------------------------------------------*/
1236 /* glue - the final glue that hold the whole thing together        */
1237 /*-----------------------------------------------------------------*/
1238 void
1239 picglue ()
1240 {
1241         char udata_name[80];
1242         FILE *vFile;
1243         FILE *asmFile;
1244         FILE *ovrFile = tempfile();
1245         
1246         addSetHead(&tmpfileSet,ovrFile);
1247         pCodeInitRegisters();
1248
1249         /* check for main() */
1250         mainf = newSymbol ("main", 0);
1251         mainf->block = 0;
1252         mainf = findSymWithLevel (SymbolTab, mainf);
1253
1254         if (!mainf || !IFFUNC_HASBODY(mainf->type))
1255         {
1256                 /* main missing -- import stack from main module */
1257                 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1258                 pic14_options.isLibrarySource = 1;
1259         }
1260
1261 #if 0
1262         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1263                 
1264                 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1265                 addpBlock(pb);
1266                 
1267                 /* entry point @ start of CSEG */
1268                 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1269                 /* put in the call to main */
1270                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1271                 
1272                 if (options.mainreturn) {
1273                         
1274                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1275                         addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1276                         
1277                 } else {
1278                         
1279                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1280                         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1281                         
1282                 }
1283         }
1284 #endif  
1285         
1286         /* At this point we've got all the code in the form of pCode structures */
1287         /* Now it needs to be rearranged into the order it should be placed in the */
1288         /* code space */
1289         
1290         movepBlock2Head('P');              // Last
1291         movepBlock2Head(code->dbName);
1292         movepBlock2Head('X');
1293         movepBlock2Head(statsg->dbName);   // First
1294         
1295         
1296         /* print the global struct definitions */
1297         if (options.debug)
1298                 cdbStructBlock (0);
1299         
1300         vFile = tempfile();
1301         
1302         addSetHead(&tmpfileSet,vFile);
1303         
1304         /* emit code for the all the variables declared */
1305         pic14emitMaps ();
1306         /* do the overlay segments */
1307         pic14emitOverlay(ovrFile);
1308         
1309         /* PENDING: this isnt the best place but it will do */
1310         if (port->general.glue_up_main) {
1311                 /* create the interrupt vector table */
1312                 pic14createInterruptVect (vFile);
1313         }
1314         
1315         AnalyzepCode('*');
1316         
1317         ReuseReg(); // ReuseReg where call tree permits
1318         
1319         InlinepCode();
1320         
1321         AnalyzepCode('*');
1322         
1323         pcode_test();
1324         
1325         
1326         /* now put it all together into the assembler file */
1327         /* create the assembler file name */
1328         
1329         if ((noAssemble || options.c1mode) && fullDstFileName)
1330         {
1331                 sprintf (buffer, fullDstFileName);
1332         }
1333         else
1334         {
1335                 sprintf (buffer, dstFileName);
1336                 strcat (buffer, ".asm");
1337         }
1338         
1339         if (!(asmFile = fopen (buffer, "w"))) {
1340                 werror (E_FILE_OPEN_ERR, buffer);
1341                 exit (1);
1342         }
1343
1344         /* prepare statistics */
1345         resetpCodeStatistics ();
1346         
1347         /* initial comments */
1348         pic14initialComments (asmFile);
1349         
1350         /* print module name */
1351         fprintf (asmFile, ";\t.module %s\n", moduleName);
1352         
1353         /* Let the port generate any global directives, etc. */
1354         if (port->genAssemblerPreamble)
1355         {
1356                 port->genAssemblerPreamble(asmFile);
1357         }
1358
1359         /* Emit the __config directive */
1360         pic14_emitConfigWord (asmFile);
1361         
1362         /* print the global variables in this module */
1363         pic14printPublics (asmFile);
1364         
1365         /* print the extern variables in this module */
1366         pic14printExterns (asmFile);
1367         
1368         /* copy the sfr segment */
1369         fprintf (asmFile, "%s", iComments2);
1370         fprintf (asmFile, "; special function registers\n");
1371         fprintf (asmFile, "%s", iComments2);
1372         copyFile (asmFile, sfr->oFile);
1373         
1374         
1375         if (udata_section_name) {
1376                 sprintf(udata_name,"%s",udata_section_name);
1377         } else {
1378                 sprintf(udata_name,"data_%s",moduleName);
1379         }
1380         fprintf (asmFile, "%s", iComments2);
1381         fprintf (asmFile, "; udata\n");
1382         fprintf (asmFile, "%s", iComments2);
1383         fprintf (asmFile, "%s\tudata\n", udata_name);
1384         copyFile (asmFile, data->oFile);
1385         
1386         /* Put all variables into a cblock */
1387         AnalyzeBanking();
1388         writeUsedRegs(asmFile);
1389         
1390         /* create the overlay segments */
1391         fprintf (asmFile, "%s", iComments2);
1392         fprintf (asmFile, "; overlayable items in internal ram \n");
1393         fprintf (asmFile, "%s", iComments2);    
1394         copyFile (asmFile, ovrFile);
1395         
1396 #if 0
1397         
1398         /* create the stack segment MOF */
1399         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1400                 fprintf (asmFile, "%s", iComments2);
1401                 fprintf (asmFile, "; Stack segment in internal ram \n");
1402                 fprintf (asmFile, "%s", iComments2);    
1403                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1404                         ";__start__stack:\n;\t.ds\t1\n\n");
1405         }
1406         
1407         /* create the idata segment */
1408         fprintf (asmFile, "%s", iComments2);
1409         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1410         fprintf (asmFile, "%s", iComments2);
1411         copyFile (asmFile, idata->oFile);
1412         
1413         /* if external stack then reserve space of it */
1414         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1415                 fprintf (asmFile, "%s", iComments2);
1416                 fprintf (asmFile, "; external stack \n");
1417                 fprintf (asmFile, "%s", iComments2);
1418                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1419                 fprintf (asmFile,";\t.ds 256\n");
1420         }
1421         
1422         /* copy xtern ram data */
1423         fprintf (asmFile, "%s", iComments2);
1424         fprintf (asmFile, "; external ram data\n");
1425         fprintf (asmFile, "%s", iComments2);
1426         copyFile (asmFile, xdata->oFile);
1427         
1428 #endif
1429         
1430         /* copy the bit segment */
1431         fprintf (asmFile, "%s", iComments2);
1432         fprintf (asmFile, "; bit data\n");
1433         fprintf (asmFile, "%s", iComments2);
1434         copyFile (asmFile, bit->oFile);
1435
1436         /* copy the interrupt vector table */
1437         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1438                 copyFile (asmFile, vFile);
1439         }
1440         
1441         /* create interupt ventor handler */
1442         pic14_emitInterruptHandler (asmFile);
1443         
1444         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1445                 /* initialize data memory */
1446                 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1447                 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1448                 /* FIXME: This is temporary.  The idata section should be used.  If 
1449                 not, we could add a special feature to the linker.  This will 
1450                 work in the mean time.  Put all initalized data in main.c */
1451                 copypCode(asmFile, statsg->dbName);
1452                 fprintf (asmFile,"\tpagesel _main\n");
1453                 fprintf (asmFile,"\tgoto _main\n");
1454         }
1455         
1456 #if 0    
1457         
1458         /* copy global & static initialisations */
1459         fprintf (asmFile, "%s", iComments2);
1460         fprintf (asmFile, "; global & static initialisations\n");
1461         fprintf (asmFile, "%s", iComments2);
1462         copypCode(asmFile, statsg->dbName);
1463         
1464 #endif
1465         
1466         /* copy over code */
1467         fprintf (asmFile, "%s", iComments2);
1468         fprintf (asmFile, "; code\n");
1469         fprintf (asmFile, "%s", iComments2);
1470         fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1471         
1472         /* unknown */
1473         copypCode(asmFile, 'X');
1474         
1475         /* _main function */
1476         copypCode(asmFile, 'M');
1477         
1478         /* other functions */
1479         copypCode(asmFile, code->dbName);
1480         
1481         /* unknown */
1482         copypCode(asmFile, 'P');
1483
1484         dumppCodeStatistics (asmFile);
1485         
1486         fprintf (asmFile,"\tend\n");
1487         
1488         fclose (asmFile);
1489         
1490         rm_tmpfiles();
1491 }