* src/pic/device.c (dump_sfr): always emit symbols
[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
77 char *udata_section_name=0;             // FIXME Temporary fix to change udata section name -- VR
78 int pic14_hasInterrupt = 0;             // Indicates whether to emit interrupt handler or not
79
80 /*-----------------------------------------------------------------*/
81 /* aopLiteral - string from a literal value                        */
82 /*-----------------------------------------------------------------*/
83 unsigned int pic14aopLiteral (value *val, int offset)
84 {
85         union {
86                 float f;
87                 unsigned char c[4];
88         } fl;
89         
90         /* if it is a float then it gets tricky */
91         /* otherwise it is fairly simple */
92         if (!IS_FLOAT(val->type)) {
93                 unsigned long v = (unsigned long) floatFromVal(val);
94                 
95                 return ( (v >> (offset * 8)) & 0xff);
96         }
97         
98         /* it is type float */
99         fl.f = (float) floatFromVal(val);
100 #ifdef WORDS_BIGENDIAN
101         return fl.c[3-offset];
102 #else
103         return fl.c[offset];
104 #endif
105         
106 }
107
108 static int
109 is_valid_identifier( const char *name )
110 {
111   char a;
112   if (!name) return 0;
113   a = *name;
114   
115   /* only accept [a-zA-Z_][a-zA-Z0-9_] */
116   if (!((a >= 'a' && a <= 'z')
117         || (a >= 'A' && a <= 'z')
118         || (a == '_')))
119     return 0;
120
121   name++;
122   while ((a = *name++))
123   {
124     if (!((a >= 'a' && a <= 'z')
125         || (a >= 'A' && a <= 'Z')
126         || (a >= '0' && a <= '9')
127         || (a == '_')))
128       return 0;
129   } // while
130
131   /* valid identifier */
132   return 1;
133 }
134
135 /* set of already emitted symbols; we store only pointers to the emitted
136  * symbol names so these MUST NO BE CHANGED afterwards... */
137 static set *symbolsEmitted = NULL;
138
139 /*-------------------------------------------------------------------*/
140 /* emitSymbolToFile - write a symbol definition only if it is not    */
141 /*                    already present                                */
142 /*-------------------------------------------------------------------*/
143 void
144 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
145 {
146         const char *sym;
147         static unsigned int sec_idx = 0;
148
149         /* workaround: variables declared via `sbit' result in a numeric
150          * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
151          * sbit is heavily used in the inc2h-generated header files!
152          */
153         if (!is_valid_identifier(name))
154         {
155           //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
156           return;
157         }
158         
159         /* check whether the symbol is already defined */
160         for (sym = (const char *) setFirstItem (symbolsEmitted);
161                 sym;
162                 sym = (const char *) setNextItem (symbolsEmitted))
163         {
164                 if (!strcmp (sym, name))
165                 {
166                         //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
167                         return;
168                 }
169         } // for
170         
171         /* new symbol -- define it */
172         //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
173         if (useEQU)
174           fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
175         else
176         {
177           /* we place each symbol into a section of its own to allow the linker
178            * to distribute the data into all available memory banks */
179           if (!section_type) section_type = "udata";
180           if (addr != -1)
181           {
182             /* absolute symbols are handled in pic14_constructAbsMap */
183             /* do nothing */
184 #if 0
185             /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
186             if (1 || !is_shared_address (addr))
187             {
188               if (globalize) fprintf (of, "\tglobal\t%s\n", name);
189               fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName,
190                   sec_idx++, "udata_ovr", addr);
191               fprintf (of, "%s\tres\t%d\n", name, size);
192             }
193             else
194             {
195               /* EQUs cannot be exported... */
196               fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
197             }
198 #endif
199           } else {
200             if (globalize) fprintf (of, "\tglobal\t%s\n", name);
201             fprintf (of, "udata_%s_%u\t%s\n", moduleName,
202                   sec_idx++, section_type);
203             fprintf (of, "%s\tres\t%d\n", name, size);
204           }
205         }
206
207         //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
208         addSet (&symbolsEmitted, (void *) name);
209 }
210
211 #define IS_DEFINED_HERE(sym)    (!IS_EXTERN(sym->etype))
212 extern int IS_CONFIG_ADDRESS( int addr );
213 static void
214 pic14_constructAbsMap (FILE *ofile)
215 {
216   memmap *maps[] = { data, sfr, NULL };
217   int i;
218   hTab *ht = NULL;
219   symbol *sym;
220   set *aliases;
221   int addr, min=-1, max=-1;
222   int size;
223   PIC_device *pic;
224   int low, high, shared;
225
226   for (i=0; maps[i] != NULL; i++)
227   {
228     for (sym = (symbol *)setFirstItem (maps[i]->syms);
229         sym; sym = setNextItem (maps[i]->syms))
230     {
231       if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
232       {
233         addr = SPEC_ADDR(sym->etype);
234
235         /* handle CONFIG words here */
236         if (IS_CONFIG_ADDRESS( addr ))
237         {
238           //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
239           //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
240           if (sym->ival) {
241             pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
242           } else {
243             fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
244           }
245           continue;
246         }
247         
248         if (max == -1 || addr > max) max = addr;
249         if (min == -1 || addr < min) min = addr;
250         //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
251         aliases = hTabItemWithKey (ht, addr);
252         if (aliases) {
253           /* May not use addSetHead, as we cannot update the
254            * list's head in the hastable `ht'. */
255           addSet (&aliases, sym);
256 #if 0
257           fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
258               __FUNCTION__, elementsInSet(aliases), sym->name, addr);
259 #endif
260         } else {
261           addSet (&aliases, sym);
262           hTabAddItem (&ht, addr, aliases);
263         } // if
264       } // if
265     } // for sym
266   } // for i
267
268   /* now emit definitions for all absolute symbols */
269   fprintf (ofile, "%s", iComments2);
270   fprintf (ofile, "; absolute symbol definitions\n");
271   fprintf (ofile, "%s", iComments2);
272   for (addr=min; addr <= max; addr++)
273   {
274     size = 1;
275     aliases = hTabItemWithKey (ht, addr);
276     if (aliases && elementsInSet(aliases)) {
277       fprintf (ofile, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
278           moduleName, addr, addr);
279       for (sym = setFirstItem (aliases); sym;
280           sym = setNextItem (aliases))
281       {
282         /* emit STATUS as well as _STATUS, required for SFRs only */
283         fprintf (ofile, "\n%s", sym->name);
284         fprintf (ofile, "\n%s", sym->rname);
285         if (getSize(sym->type) > size) {
286           size = getSize(sym->type);
287         }
288         addSet (&symbolsEmitted, (void *) sym->name);
289         addSet (&symbolsEmitted, (void *) sym->rname);
290       } // for
291       fprintf (ofile, "\tres\t%d\n", size);
292     } // if
293   } // for i
294
295   /* also emit STK symbols
296    * XXX: This is ugly and fails as soon as devices start to get
297    *      differently sized sharebanks, since STK12 will be
298    *      required by larger devices but only up to STK03 might
299    *      be defined using smaller devices. */
300   fprintf (ofile, "\n");
301   shared = pic14_getSharedStack(&low, &high, &size);
302   if (!pic14_options.isLibrarySource)
303   {
304     pic = pic14_getPIC();
305
306     fprintf (ofile, "\tglobal PSAVE\n");
307     fprintf (ofile, "\tglobal SSAVE\n");
308     fprintf (ofile, "\tglobal WSAVE\n");
309     for (i = size - 4; i >= 0; i--) {
310       fprintf (ofile, "\tglobal STK%02d\n", i);
311     } // for i
312
313     // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
314     // banks, sigh...
315     if (1 || !shared) {
316         // for single banked devices: use normal, "banked" RAM
317         fprintf (ofile, "sharebank udata_ovr 0x%04X\n", low);
318     } else {
319         // for devices with at least two banks, require a sharebank section
320         fprintf (ofile, "sharebank udata_shr\n");
321     }
322     fprintf (ofile, "PSAVE\tres 1\n");
323     fprintf (ofile, "SSAVE\tres 1\n");
324     fprintf (ofile, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
325     /* fill rest of sharebank with stack STKxx .. STK00 */
326     for (i = size - 4; i >= 0; i--) {
327       fprintf (ofile, "STK%02d\tres 1\n", i);
328     } // for i
329   } else {
330     /* declare STKxx as extern for all files
331      * except the one containing main() */
332     fprintf (ofile, "\textern PSAVE\n");
333     fprintf (ofile, "\textern SSAVE\n");
334     fprintf (ofile, "\textern WSAVE\n");
335     for (i = size - 4; i >= 0; i--) {
336         char buffer[128];
337         SNPRINTF(&buffer[0], 127, "STK%02d", i);
338         fprintf (ofile, "\textern %s\n", &buffer[0]);
339         addSet (&symbolsEmitted, (void *) &buffer[0]);
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         pic14emitStaticSeg (c_abs);
978 }
979
980 /*-----------------------------------------------------------------*/
981 /* createInterruptVect - creates the interrupt vector              */
982 /*-----------------------------------------------------------------*/
983 static void
984 pic14createInterruptVect (FILE * vFile)
985 {
986         mainf = newSymbol ("main", 0);
987         mainf->block = 0;
988         
989         /* only if the main function exists */
990         if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
991         {
992                 struct options *op = &options;
993                 if (!(op->cc_only || noAssemble))
994                         //      werror (E_NO_MAIN);
995                         fprintf(stderr,"WARNING: function 'main' undefined\n");
996                 return;
997         }
998         
999         /* if the main is only a prototype ie. no body then do nothing */
1000         if (!IFFUNC_HASBODY(mainf->type))
1001         {
1002                 /* if ! compile only then main function should be present */
1003                 if (!(options.cc_only || noAssemble))
1004                         //      werror (E_NO_MAIN);
1005                         fprintf(stderr,"WARNING: function 'main' undefined\n");
1006                 return;
1007         }
1008         
1009         fprintf (vFile, "%s", iComments2);
1010         fprintf (vFile, "; reset vector \n");
1011         fprintf (vFile, "%s", iComments2);
1012         fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1013         fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1014         fprintf( vFile, "\tpagesel __sdcc_gsinit_startup\n");
1015         fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1016 }
1017
1018
1019 /*-----------------------------------------------------------------*/
1020 /* initialComments - puts in some initial comments                 */
1021 /*-----------------------------------------------------------------*/
1022 static void
1023 pic14initialComments (FILE * afile)
1024 {
1025         initialComments (afile);
1026         fprintf (afile, "; PIC port for the 14-bit core\n");
1027         fprintf (afile, iComments2);
1028         
1029 }
1030
1031 int
1032 pic14_stringInSet(const char *str, set **world, int autoAdd)
1033 {
1034   char *s;
1035
1036   if (!str) return 1;
1037   assert(world);
1038
1039   for (s = setFirstItem(*world); s; s = setNextItem(*world))
1040   {
1041     /* found in set */
1042     if (0 == strcmp(s, str)) return 1;
1043   }
1044
1045   /* not found */
1046   if (autoAdd) addSet(world, Safe_strdup(str));
1047   return 0;
1048 }
1049
1050 static int
1051 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1052 {
1053   static set *emitted = NULL;
1054
1055   if (!pic14_stringInSet(sym, &emitted, 1)) {
1056     /* sym was not in emittedSymbols */
1057     if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1058       /* sym is not a locally defined function---avoid bug #1443651 */
1059       fprintf( file, fmt, sym );
1060       return 0;
1061     }
1062   }
1063   return 1;
1064 }
1065
1066 /*-----------------------------------------------------------------*/
1067 /* printExterns - generates extern for external variables          */
1068 /*-----------------------------------------------------------------*/
1069 static void
1070 pic14printExterns (FILE * afile)
1071 {
1072         symbol *sym;
1073         
1074         fprintf (afile, "%s", iComments2);
1075         fprintf (afile, "; extern variables in this module\n");
1076         fprintf (afile, "%s", iComments2);
1077         
1078         for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1079                 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1080 }
1081
1082 /*-----------------------------------------------------------------*/
1083 /* printPublics - generates .global for publics                    */
1084 /*-----------------------------------------------------------------*/
1085 static void
1086 pic14printPublics (FILE * afile)
1087 {
1088   symbol *sym;
1089
1090   fprintf (afile, "%s", iComments2);
1091   fprintf (afile, "; public variables in this module\n");
1092   fprintf (afile, "%s", iComments2);
1093
1094   for (sym = setFirstItem (publics); sym;
1095       sym = setNextItem (publics)) {
1096
1097     if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1098       if (!IS_BITVAR(sym->type))
1099         pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1100     } else {
1101       /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1102       /* Not any longer! */
1103       //if (!SPEC_ABSA (sym->etype))
1104       pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1105     }
1106   }
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* emitOverlay - will emit code for the overlay stuff              */
1111 /*-----------------------------------------------------------------*/
1112 static void
1113 pic14emitOverlay (FILE * afile)
1114 {
1115         set *ovrset;
1116         
1117         /*  if (!elementsInSet (ovrSetSets))*/
1118         
1119         /* the hack below, fixes translates for devices which
1120         * only have udata_shr memory */
1121         fprintf (afile, "%s\t%s\n",
1122                 (elementsInSet(ovrSetSets)?"":";"),
1123                 port->mem.overlay_name);
1124         
1125         /* for each of the sets in the overlay segment do */
1126         for (ovrset = setFirstItem (ovrSetSets); ovrset;
1127         ovrset = setNextItem (ovrSetSets))
1128         {
1129                 
1130                 symbol *sym;
1131                 
1132                 if (elementsInSet (ovrset))
1133                 {
1134                 /* this dummy area is used to fool the assembler
1135                 otherwise the assembler will append each of these
1136                 declarations into one chunk and will not overlay
1137                         sad but true */
1138                         
1139                         /* I don't think this applies to us. We are using gpasm.  CRF */
1140                         
1141                         fprintf (afile, ";\t.area _DUMMY\n");
1142                         /* output the area informtion */
1143                         fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);      /* MOF */
1144                 }
1145                 
1146                 for (sym = setFirstItem (ovrset); sym;
1147                 sym = setNextItem (ovrset))
1148                 {
1149                         
1150                         /* if extern then do nothing */
1151                         if (IS_EXTERN (sym->etype))
1152                                 continue;
1153                         
1154                                 /* if allocation required check is needed
1155                                 then check if the symbol really requires
1156                         allocation only for local variables */
1157                         if (!IS_AGGREGATE (sym->type) &&
1158                                 !(sym->_isparm && !IS_REGPARM (sym->etype))
1159                                 && !sym->allocreq && sym->level)
1160                                 continue;
1161                         
1162                                 /* if global variable & not static or extern
1163                         and addPublics allowed then add it to the public set */
1164                         if ((sym->_isparm && !IS_REGPARM (sym->etype))
1165                                 && !IS_STATIC (sym->etype))
1166                                 addSetHead (&publics, sym);
1167                         
1168                                 /* if extern then do nothing or is a function
1169                         then do nothing */
1170                         if (IS_FUNC (sym->type))
1171                                 continue;
1172                         
1173                         /* print extra debug info if required */
1174                         if (options.debug || sym->level == 0)
1175                         {
1176                                 if (!sym->level)
1177                                 {               /* global */
1178                                         if (IS_STATIC (sym->etype))
1179                                                 fprintf (afile, "F%s_", moduleName);    /* scope is file */
1180                                         else
1181                                                 fprintf (afile, "G_");  /* scope is global */
1182                                 }
1183                                 else
1184                                         /* symbol is local */
1185                                         fprintf (afile, "L%s_",
1186                                         (sym->localof ? sym->localof->name : "-null-"));
1187                                 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1188                         }
1189                         
1190                         /* if is has an absolute address then generate
1191                         an equate for this no need to allocate space */
1192                         if (SPEC_ABSA (sym->etype))
1193                         {
1194                                 
1195                                 if (options.debug || sym->level == 0)
1196                                         fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1197                                 
1198                                 fprintf (afile, "%s\t=\t0x%04x\n",
1199                                         sym->rname,
1200                                         SPEC_ADDR (sym->etype));
1201                         }
1202                         else
1203                         {
1204                                 if (options.debug || sym->level == 0)
1205                                         fprintf (afile, "==.\n");
1206                                 
1207                                 /* allocate space */
1208                                 fprintf (afile, "%s:\n", sym->rname);
1209                                 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1210                         }
1211                         
1212                 }
1213         }
1214 }
1215
1216
1217 void
1218 pic14_emitInterruptHandler (FILE * asmFile)
1219 {
1220         if (pic14_hasInterrupt)
1221         {
1222
1223                 fprintf (asmFile, "%s", iComments2);
1224                 fprintf (asmFile, "; interrupt and initialization code\n");
1225                 fprintf (asmFile, "%s", iComments2);
1226                 // Note - for mplink may have to enlarge section vectors in .lnk file
1227                 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1228                 //       source files's code segment (interrupt.c -> code_interrupt)
1229                 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1230                 
1231                 /* interrupt service routine */
1232                 fprintf (asmFile, "__sdcc_interrupt\n");
1233                 copypCode(asmFile, 'I');
1234         }       
1235 }
1236
1237 /*-----------------------------------------------------------------*/
1238 /* glue - the final glue that hold the whole thing together        */
1239 /*-----------------------------------------------------------------*/
1240 void
1241 picglue ()
1242 {
1243         char udata_name[80];
1244         FILE *vFile;
1245         FILE *asmFile;
1246         FILE *ovrFile = tempfile();
1247         
1248         addSetHead(&tmpfileSet,ovrFile);
1249         pCodeInitRegisters();
1250
1251         /* check for main() */
1252         mainf = newSymbol ("main", 0);
1253         mainf->block = 0;
1254         mainf = findSymWithLevel (SymbolTab, mainf);
1255
1256         if (!mainf || !IFFUNC_HASBODY(mainf->type))
1257         {
1258                 /* main missing -- import stack from main module */
1259                 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1260                 pic14_options.isLibrarySource = 1;
1261         }
1262
1263 #if 0
1264         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1265                 
1266                 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1267                 addpBlock(pb);
1268                 
1269                 /* entry point @ start of CSEG */
1270                 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1271                 /* put in the call to main */
1272                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1273                 
1274                 if (options.mainreturn) {
1275                         
1276                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1277                         addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1278                         
1279                 } else {
1280                         
1281                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1282                         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1283                         
1284                 }
1285         }
1286 #endif  
1287         
1288         /* At this point we've got all the code in the form of pCode structures */
1289         /* Now it needs to be rearranged into the order it should be placed in the */
1290         /* code space */
1291         
1292         movepBlock2Head('P');              // Last
1293         movepBlock2Head(code->dbName);
1294         movepBlock2Head('X');
1295         movepBlock2Head(statsg->dbName);   // First
1296         
1297         
1298         /* print the global struct definitions */
1299         if (options.debug)
1300                 cdbStructBlock (0);
1301         
1302         vFile = tempfile();
1303         
1304         addSetHead(&tmpfileSet,vFile);
1305         
1306         /* emit code for the all the variables declared */
1307         pic14emitMaps ();
1308         /* do the overlay segments */
1309         pic14emitOverlay(ovrFile);
1310         
1311         /* PENDING: this isnt the best place but it will do */
1312         if (port->general.glue_up_main) {
1313                 /* create the interrupt vector table */
1314                 pic14createInterruptVect (vFile);
1315         }
1316         
1317         AnalyzepCode('*');
1318         
1319         ReuseReg(); // ReuseReg where call tree permits
1320         
1321         InlinepCode();
1322         
1323         AnalyzepCode('*');
1324         
1325         pcode_test();
1326         
1327         
1328         /* now put it all together into the assembler file */
1329         /* create the assembler file name */
1330         
1331         if ((noAssemble || options.c1mode) && fullDstFileName)
1332         {
1333                 sprintf (buffer, fullDstFileName);
1334         }
1335         else
1336         {
1337                 sprintf (buffer, dstFileName);
1338                 strcat (buffer, ".asm");
1339         }
1340         
1341         if (!(asmFile = fopen (buffer, "w"))) {
1342                 werror (E_FILE_OPEN_ERR, buffer);
1343                 exit (1);
1344         }
1345
1346         /* prepare statistics */
1347         resetpCodeStatistics ();
1348         
1349         /* initial comments */
1350         pic14initialComments (asmFile);
1351         
1352         /* print module name */
1353         fprintf (asmFile, ";\t.module %s\n", moduleName);
1354         
1355         /* Let the port generate any global directives, etc. */
1356         if (port->genAssemblerPreamble)
1357         {
1358                 port->genAssemblerPreamble(asmFile);
1359         }
1360
1361         /* Emit the __config directive */
1362         pic14_emitConfigWord (asmFile);
1363         
1364         /* print the global variables in this module */
1365         pic14printPublics (asmFile);
1366         
1367         /* print the extern variables in this module */
1368         pic14printExterns (asmFile);
1369         
1370         /* copy the sfr segment */
1371         fprintf (asmFile, "%s", iComments2);
1372         fprintf (asmFile, "; special function registers\n");
1373         fprintf (asmFile, "%s", iComments2);
1374         copyFile (asmFile, sfr->oFile);
1375         
1376         
1377         if (udata_section_name) {
1378                 sprintf(udata_name,"%s",udata_section_name);
1379         } else {
1380                 sprintf(udata_name,"data_%s",moduleName);
1381         }
1382         fprintf (asmFile, "%s", iComments2);
1383         fprintf (asmFile, "; udata\n");
1384         fprintf (asmFile, "%s", iComments2);
1385         fprintf (asmFile, "%s\tudata\n", udata_name);
1386         copyFile (asmFile, data->oFile);
1387         
1388         /* Put all variables into a cblock */
1389         AnalyzeBanking();
1390         writeUsedRegs(asmFile);
1391         
1392         /* create the overlay segments */
1393         fprintf (asmFile, "%s", iComments2);
1394         fprintf (asmFile, "; overlayable items in internal ram \n");
1395         fprintf (asmFile, "%s", iComments2);    
1396         copyFile (asmFile, ovrFile);
1397         
1398 #if 0
1399         
1400         /* create the stack segment MOF */
1401         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1402                 fprintf (asmFile, "%s", iComments2);
1403                 fprintf (asmFile, "; Stack segment in internal ram \n");
1404                 fprintf (asmFile, "%s", iComments2);    
1405                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1406                         ";__start__stack:\n;\t.ds\t1\n\n");
1407         }
1408         
1409         /* create the idata segment */
1410         fprintf (asmFile, "%s", iComments2);
1411         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1412         fprintf (asmFile, "%s", iComments2);
1413         copyFile (asmFile, idata->oFile);
1414         
1415         /* if external stack then reserve space of it */
1416         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1417                 fprintf (asmFile, "%s", iComments2);
1418                 fprintf (asmFile, "; external stack \n");
1419                 fprintf (asmFile, "%s", iComments2);
1420                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1421                 fprintf (asmFile,";\t.ds 256\n");
1422         }
1423         
1424         /* copy xtern ram data */
1425         fprintf (asmFile, "%s", iComments2);
1426         fprintf (asmFile, "; external ram data\n");
1427         fprintf (asmFile, "%s", iComments2);
1428         copyFile (asmFile, xdata->oFile);
1429         
1430 #endif
1431         
1432         /* copy the bit segment */
1433         fprintf (asmFile, "%s", iComments2);
1434         fprintf (asmFile, "; bit data\n");
1435         fprintf (asmFile, "%s", iComments2);
1436         copyFile (asmFile, bit->oFile);
1437
1438         /* copy the interrupt vector table */
1439         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1440                 copyFile (asmFile, vFile);
1441         }
1442         
1443         /* create interupt ventor handler */
1444         pic14_emitInterruptHandler (asmFile);
1445         
1446         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1447                 /* initialize data memory */
1448                 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1449                 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1450                 /* FIXME: This is temporary.  The idata section should be used.  If 
1451                 not, we could add a special feature to the linker.  This will 
1452                 work in the mean time.  Put all initalized data in main.c */
1453                 copypCode(asmFile, statsg->dbName);
1454                 fprintf (asmFile,"\tpagesel _main\n");
1455                 fprintf (asmFile,"\tgoto _main\n");
1456         }
1457         
1458 #if 0    
1459         
1460         /* copy global & static initialisations */
1461         fprintf (asmFile, "%s", iComments2);
1462         fprintf (asmFile, "; global & static initialisations\n");
1463         fprintf (asmFile, "%s", iComments2);
1464         copypCode(asmFile, statsg->dbName);
1465         
1466 #endif
1467         
1468         /* copy over code */
1469         fprintf (asmFile, "%s", iComments2);
1470         fprintf (asmFile, "; code\n");
1471         fprintf (asmFile, "%s", iComments2);
1472         fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1473         
1474         /* unknown */
1475         copypCode(asmFile, 'X');
1476         
1477         /* _main function */
1478         copypCode(asmFile, 'M');
1479         
1480         /* other functions */
1481         copypCode(asmFile, code->dbName);
1482         
1483         /* unknown */
1484         copypCode(asmFile, 'P');
1485
1486         dumppCodeStatistics (asmFile);
1487         
1488         fprintf (asmFile,"\tend\n");
1489         
1490         fclose (asmFile);
1491         
1492         rm_tmpfiles();
1493 }