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