c007753353c15070c71159495b0287a43ffedf62
[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
31
32 #ifdef WORDS_BIGENDIAN
33   #define _ENDIAN(x)  (3-x)
34 #else
35   #define _ENDIAN(x)  (x)
36 #endif
37
38 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
39
40 extern symbol *interrupts[256];
41 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
42 extern int noAlloc;
43 extern set *publics;
44 extern set *externs;
45 extern unsigned maxInterrupts;
46 extern int maxRegBank;
47 extern symbol *mainf;
48 extern char *VersionString;
49 extern FILE *codeOutFile;
50 extern set *tmpfileSet;
51 extern set *tmpfileNameSet;
52 extern char *iComments1;
53 extern char *iComments2;
54 //extern void emitStaticSeg (memmap * map);
55
56 extern DEFSETFUNC (closeTmpFiles);
57 extern DEFSETFUNC (rmTmpFiles);
58
59 extern void AnalyzeBanking (void);
60 extern void copyFile (FILE * dest, FILE * src);
61 extern void InlinepCode(void);
62 extern void writeUsedRegs(FILE *);
63
64 extern void initialComments (FILE * afile);
65 extern void printPublics (FILE * afile);
66
67 extern void printChar (FILE * ofile, char *s, int plen);
68 void  pCodeInitRegisters(void);
69 int getConfigWord(int address);
70
71 char *udata_section_name="udata";               // FIXME Temporary fix to change udata section name -- VR
72
73 /*-----------------------------------------------------------------*/
74 /* aopLiteral - string from a literal value                        */
75 /*-----------------------------------------------------------------*/
76 int pic14aopLiteral (value *val, int offset)
77 {
78   union {
79     float f;
80     unsigned char c[4];
81   } fl;
82
83   /* if it is a float then it gets tricky */
84   /* otherwise it is fairly simple */
85   if (!IS_FLOAT(val->type)) {
86     unsigned long v = (unsigned long) floatFromVal(val);
87
88     return ( (v >> (offset * 8)) & 0xff);
89   }
90
91   /* it is type float */
92   fl.f = (float) floatFromVal(val);
93 #ifdef WORDS_BIGENDIAN
94   return fl.c[3-offset];
95 #else
96   return fl.c[offset];
97 #endif
98
99 }
100
101
102 /*-----------------------------------------------------------------*/
103 /* emitRegularMap - emit code for maps with no special cases       */
104 /*-----------------------------------------------------------------*/
105 static void
106 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
107 {
108   symbol *sym;
109   int bitvars = 0;;
110
111   /* print the area name */
112   if (addPublics)
113     fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
114
115   for (sym = setFirstItem (map->syms); sym;
116        sym = setNextItem (map->syms)) {
117
118     //printf("%s\n",sym->name);
119
120     /* if extern then add it into the extern list */
121     if (IS_EXTERN (sym->etype)) {
122       addSetHead (&externs, sym);
123       continue;
124     }
125
126     /* if allocation required check is needed
127        then check if the symbol really requires
128        allocation only for local variables */
129     if (arFlag && !IS_AGGREGATE (sym->type) &&
130         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
131         !sym->allocreq && sym->level)
132       continue;
133
134     /* if global variable & not static or extern
135        and addPublics allowed then add it to the public set */
136     if ((sym->level == 0 ||
137          (sym->_isparm && !IS_REGPARM (sym->etype))) &&
138         addPublics &&
139         !IS_STATIC (sym->etype))
140       addSetHead (&publics, sym);
141
142     /* if extern then do nothing or is a function
143        then do nothing */
144     if (IS_FUNC (sym->type))
145       continue;
146 #if 0
147     /* print extra debug info if required */
148     if (options.debug || sym->level == 0)
149       {
150         if (!sym->level)        /* global */
151           if (IS_STATIC (sym->etype))
152             fprintf (map->oFile, "F%s_", moduleName);           /* scope is file */
153           else
154             fprintf (map->oFile, "G_"); /* scope is global */
155         else
156           /* symbol is local */
157           fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
158         fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
159       }
160 #endif
161
162     /* if it has an absolute address then generate
163        an equate for this no need to allocate space */
164     if (SPEC_ABSA (sym->etype))
165       {
166         //if (options.debug || sym->level == 0)
167         //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
168
169         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
170                  sym->rname,
171                  SPEC_ADDR (sym->etype));
172       }
173      else
174        {
175          /* allocate space */
176
177          /* If this is a bit variable, then allocate storage after 8 bits have been declared */
178          /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
179          /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
180          if (IS_BITVAR (sym->etype))
181            {
182              bitvars++;
183            }
184          else
185            {
186              fprintf (map->oFile, "%s\tres\t%d\n", sym->rname,getSize (sym->type) & 0xffff);
187              /*
188              {
189                int i, size;
190
191                if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
192                  {
193                    for (i = 1; i < size; i++)
194                      fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
195                  }
196              }
197              */
198            }
199          //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
200        }
201
202     /* if it has a initial value then do it only if
203        it is a global variable */
204     if (sym->ival && sym->level == 0) {
205       ast *ival = NULL;
206             
207       if (IS_AGGREGATE (sym->type))
208         ival = initAggregates (sym, sym->ival, NULL);
209       else
210         ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
211                         decorateType (resolveSymbols (list2expr (sym->ival))));
212       codeOutFile = statsg->oFile;
213       GcurMemmap = statsg;
214       eBBlockFromiCode (iCodeFromAst (ival));
215       sym->ival = NULL;
216     }
217   }
218 }
219
220
221 /*-----------------------------------------------------------------*/
222 /* printIvalType - generates ival for int/char                     */
223 /*-----------------------------------------------------------------*/
224 static void 
225 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
226 {
227   value *val;
228   unsigned long ulval;
229
230   //fprintf(stderr, "%s\n",__FUNCTION__);
231
232   /* if initList is deep */
233   if (ilist->type == INIT_DEEP)
234     ilist = ilist->init.deep;
235
236   if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
237     werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
238   }
239
240   if (!(val = list2val (ilist))) {
241     // assuming a warning has been thrown
242     val=constVal("0");
243   }
244
245   if (val->type != type) {
246     val = valCastLiteral(type, floatFromVal(val));
247   }
248
249   if(val) 
250     ulval = (unsigned long) floatFromVal (val);
251   else
252     ulval =0;
253
254   switch (getSize (type)) {
255   case 1:
256     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
257     break;
258
259   case 2:
260     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
261     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
262     break;
263
264   case 4:
265     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
266     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
267     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
268     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
269     break;
270   }
271 }
272
273 /*-----------------------------------------------------------------*/
274 /* printIvalChar - generates initital value for character array    */
275 /*-----------------------------------------------------------------*/
276 static int 
277 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
278 {
279   value *val;
280   int remain;
281
282   if(!pb)
283     return 0;
284
285   //fprintf(stderr, "%s\n",__FUNCTION__);
286   if (!s)
287     {
288
289       val = list2val (ilist);
290       /* if the value is a character string  */
291       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
292         {
293           if (!DCL_ELEM (type))
294             DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
295
296           //printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
297           //fprintf(stderr, "%s omitting call to printChar\n",__FUNCTION__);
298           addpCode2pBlock(pb,newpCodeCharP(";omitting call to printChar"));
299
300           if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
301             while (remain--)
302               //tfprintf (oFile, "\t!db !constbyte\n", 0);
303               addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
304           return 1;
305         }
306       else
307         return 0;
308     }
309   else {
310     //printChar (oFile, s, strlen (s) + 1);
311
312     for(remain=0; remain<(int)strlen(s); remain++) {
313       addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
314       //fprintf(stderr,"0x%02x ",s[remain]);
315     }
316     //fprintf(stderr,"\n");
317   }
318   return 1;
319 }
320
321 /*-----------------------------------------------------------------*/
322 /* printIvalArray - generates code for array initialization        */
323 /*-----------------------------------------------------------------*/
324 static void 
325 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
326                 pBlock *pb)
327 {
328   initList *iloop;
329   int lcnt = 0, size = 0;
330
331   if(!pb)
332     return;
333
334   /* take care of the special   case  */
335   /* array of characters can be init  */
336   /* by a string                      */
337   if (IS_CHAR (type->next)) {
338     //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
339     if (!IS_LITERAL(list2val(ilist)->etype)) {
340       werror (W_INIT_WRONG);
341       return;
342     }
343     if (printIvalChar (type,
344                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
345                        pb, SPEC_CVAL (sym->etype).v_char))
346       return;
347   }
348   /* not the special case             */
349   if (ilist->type != INIT_DEEP)
350     {
351       werror (E_INIT_STRUCT, sym->name);
352       return;
353     }
354
355   iloop = ilist->init.deep;
356   lcnt = DCL_ELEM (type);
357
358   for (;;)
359     {
360       //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
361       size++;
362       printIval (sym, type->next, iloop, pb);
363       iloop = (iloop ? iloop->next : NULL);
364
365
366       /* if not array limits given & we */
367       /* are out of initialisers then   */
368       if (!DCL_ELEM (type) && !iloop)
369         break;
370
371       /* no of elements given and we    */
372       /* have generated for all of them */
373       if (!--lcnt) {
374         /* if initializers left */
375         if (iloop) {
376           werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
377         }
378         break;
379       }
380     }
381
382   /* if we have not been given a size  */
383   if (!DCL_ELEM (type))
384     DCL_ELEM (type) = size;
385
386   return;
387 }
388
389 /*-----------------------------------------------------------------*/
390 /* printIval - generates code for initial value                    */
391 /*-----------------------------------------------------------------*/
392 static void 
393 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
394 {
395   if (!ilist || !pb)
396     return;
397
398   /* if structure then    */
399   if (IS_STRUCT (type))
400     {
401       //fprintf(stderr,"%s struct\n",__FUNCTION__);
402       //printIvalStruct (sym, type, ilist, oFile);
403       return;
404     }
405
406   /* if this is a pointer */
407   if (IS_PTR (type))
408     {
409       //fprintf(stderr,"%s pointer\n",__FUNCTION__);
410       //printIvalPtr (sym, type, ilist, oFile);
411       return;
412     }
413
414   /* if this is an array   */
415   if (IS_ARRAY (type))
416     {
417       //fprintf(stderr,"%s array\n",__FUNCTION__);
418       printIvalArray (sym, type, ilist, pb);
419       return;
420     }
421
422   /* if type is SPECIFIER */
423   if (IS_SPEC (type))
424     {
425       //fprintf(stderr,"%s spec\n",__FUNCTION__);
426       printIvalType (sym, type, ilist, pb);
427       return;
428     }
429 }
430
431 extern void pCodeConstString(char *name, char *value);
432 /*-----------------------------------------------------------------*/
433 /* emitStaticSeg - emitcode for the static segment                 */
434 /*-----------------------------------------------------------------*/
435 static void
436 pic14emitStaticSeg (memmap * map)
437 {
438   symbol *sym;
439
440   fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
441
442   //fprintf(stderr, "%s\n",__FUNCTION__);
443
444   /* for all variables in this segment do */
445   for (sym = setFirstItem (map->syms); sym;
446        sym = setNextItem (map->syms))
447     {
448       /* if it is "extern" then do nothing */
449       if (IS_EXTERN (sym->etype))
450         continue;
451
452       /* if it is not static add it to the public
453          table */
454       if (!IS_STATIC (sym->etype))
455         addSetHead (&publics, sym);
456
457       /* print extra debug info if required */
458       if (options.debug || sym->level == 0)
459         {
460           if (!sym->level)
461             {                   /* global */
462               if (IS_STATIC (sym->etype))
463                 fprintf (code->oFile, "F%s_", moduleName);      /* scope is file */
464               else
465                 fprintf (code->oFile, "G_");    /* scope is global */
466             }
467           else
468             /* symbol is local */
469             fprintf (code->oFile, "L%s_",
470                      (sym->localof ? sym->localof->name : "-null-"));
471           fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
472
473         }
474
475       /* if it has an absolute address */
476       if (SPEC_ABSA (sym->etype))
477         {
478           if (options.debug || sym->level == 0)
479             fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
480
481           fprintf (code->oFile, "%s\t=\t0x%04x\n",
482                    sym->rname,
483                    SPEC_ADDR (sym->etype));
484         }
485       else
486         {
487           if (options.debug || sym->level == 0)
488             fprintf (code->oFile, " == .\n");
489
490           /* if it has an initial value */
491           if (sym->ival)
492             {
493               pBlock *pb;
494
495               fprintf (code->oFile, "%s:\n", sym->rname);
496               noAlloc++;
497               resolveIvalSym (sym->ival);
498               //printIval (sym, sym->type, sym->ival, code->oFile);
499               pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
500               addpBlock(pb);
501               addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
502
503               printIval (sym, sym->type, sym->ival, pb);
504               noAlloc--;
505             }
506           else
507             {
508
509               /* allocate space */
510               fprintf (code->oFile, "%s:\n", sym->rname);
511               /* special case for character strings */
512               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
513                   SPEC_CVAL (sym->etype).v_char)
514                 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
515                 /*printChar (code->oFile,
516                            SPEC_CVAL (sym->etype).v_char,
517                            strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
518               else
519                 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
520             }
521         }
522     }
523
524 }
525
526
527 /*-----------------------------------------------------------------*/
528 /* emitMaps - emits the code for the data portion the code         */
529 /*-----------------------------------------------------------------*/
530 static void
531 pic14emitMaps ()
532 {
533   /* no special considerations for the following
534      data, idata & bit & xdata */
535   pic14emitRegularMap (data, TRUE, TRUE);
536   pic14emitRegularMap (idata, TRUE, TRUE);
537   pic14emitRegularMap (bit, TRUE, FALSE);
538   pic14emitRegularMap (xdata, TRUE, TRUE);
539   pic14emitRegularMap (sfr, FALSE, FALSE);
540   pic14emitRegularMap (sfrbit, FALSE, FALSE);
541   pic14emitRegularMap (code, TRUE, FALSE);
542   pic14emitStaticSeg (statsg);
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* createInterruptVect - creates the interrupt vector              */
547 /*-----------------------------------------------------------------*/
548 static void
549 pic14createInterruptVect (FILE * vFile)
550 {
551   mainf = newSymbol ("main", 0);
552   mainf->block = 0;
553
554   /* only if the main function exists */
555   if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
556     {
557       if (!options.cc_only)
558         werror (E_NO_MAIN);
559       return;
560     }
561
562   /* if the main is only a prototype ie. no body then do nothing */
563   if (!IFFUNC_HASBODY(mainf->type))
564     {
565       /* if ! compile only then main function should be present */
566       if (!options.cc_only)
567         werror (E_NO_MAIN);
568       return;
569     }
570
571   fprintf (vFile, "%s", iComments2);
572   fprintf (vFile, "; config word \n");
573   fprintf (vFile, "%s", iComments2);
574   fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
575
576   fprintf (vFile, "%s", iComments2);
577   fprintf (vFile, "; reset vector \n");
578   fprintf (vFile, "%s", iComments2);
579   fprintf (vFile, "STARTUP\t%s\n", CODE_NAME);
580   fprintf (vFile, "\tnop\n"); /* first location used by incircuit debugger */
581   fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
582 /* during an interrupt PCLATH must be cleared before a goto  - delete me
583   fprintf (vFile, "\tnop\n");
584   fprintf (vFile, "\tgoto\t__sdcc_interrupt\n");
585 */
586 }
587
588
589 /*-----------------------------------------------------------------*/
590 /* initialComments - puts in some initial comments                 */
591 /*-----------------------------------------------------------------*/
592 static void
593 pic14initialComments (FILE * afile)
594 {
595   initialComments (afile);
596   fprintf (afile, "; PIC port for the 14-bit core\n");
597   fprintf (afile, iComments2);
598
599 }
600
601 /*-----------------------------------------------------------------*/
602 /* printExterns - generates extern for external variables          */
603 /*-----------------------------------------------------------------*/
604 static void
605 pic14printExterns (FILE * afile)
606 {
607   symbol *sym;
608
609   fprintf (afile, "%s", iComments2);
610   fprintf (afile, "; extern variables in this module\n");
611   fprintf (afile, "%s", iComments2);
612
613   for (sym = setFirstItem (externs); sym;
614        sym = setNextItem (externs))
615     fprintf (afile, "\textern %s\n", sym->rname);
616 }
617
618 /*-----------------------------------------------------------------*/
619 /* printPublics - generates .global for publics                    */
620 /*-----------------------------------------------------------------*/
621 static void
622 pic14printPublics (FILE * afile)
623 {
624   symbol *sym;
625
626   fprintf (afile, "%s", iComments2);
627   fprintf (afile, "; publics variables in this module\n");
628   fprintf (afile, "%s", iComments2);
629
630   for (sym = setFirstItem (publics); sym;
631        sym = setNextItem (publics)) {
632     if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
633       if (!IS_BITVAR(sym->type))
634         fprintf (afile, "\tglobal %s\n", sym->rname);
635     } else
636       fprintf (afile, ";\tglobal %s\n", sym->rname);
637   }
638 }
639
640 /*-----------------------------------------------------------------*/
641 /* emitOverlay - will emit code for the overlay stuff              */
642 /*-----------------------------------------------------------------*/
643 static void
644 pic14emitOverlay (FILE * afile)
645 {
646   set *ovrset;
647
648 /*  if (!elementsInSet (ovrSetSets))*/
649
650   /* the hack below, fixes translates for devices which
651    * only have udata_shr memory */
652   fprintf (afile, "%s\t%s\n",
653         (elementsInSet(ovrSetSets)?"":";"),
654         port->mem.overlay_name);
655
656   /* for each of the sets in the overlay segment do */
657   for (ovrset = setFirstItem (ovrSetSets); ovrset;
658        ovrset = setNextItem (ovrSetSets))
659     {
660
661       symbol *sym;
662
663       if (elementsInSet (ovrset))
664         {
665           /* this dummy area is used to fool the assembler
666              otherwise the assembler will append each of these
667              declarations into one chunk and will not overlay
668              sad but true */
669              
670           /* I don't think this applies to us. We are using gpasm.  CRF */
671           
672           fprintf (afile, ";\t.area _DUMMY\n");
673           /* output the area informtion */
674           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
675         }
676
677       for (sym = setFirstItem (ovrset); sym;
678            sym = setNextItem (ovrset))
679         {
680
681           /* if extern then do nothing */
682           if (IS_EXTERN (sym->etype))
683             continue;
684
685           /* if allocation required check is needed
686              then check if the symbol really requires
687              allocation only for local variables */
688           if (!IS_AGGREGATE (sym->type) &&
689               !(sym->_isparm && !IS_REGPARM (sym->etype))
690               && !sym->allocreq && sym->level)
691             continue;
692
693           /* if global variable & not static or extern
694              and addPublics allowed then add it to the public set */
695           if ((sym->_isparm && !IS_REGPARM (sym->etype))
696               && !IS_STATIC (sym->etype))
697             addSetHead (&publics, sym);
698
699           /* if extern then do nothing or is a function
700              then do nothing */
701           if (IS_FUNC (sym->type))
702             continue;
703
704           /* print extra debug info if required */
705           if (options.debug || sym->level == 0)
706             {
707               if (!sym->level)
708                 {               /* global */
709                   if (IS_STATIC (sym->etype))
710                     fprintf (afile, "F%s_", moduleName);        /* scope is file */
711                   else
712                     fprintf (afile, "G_");      /* scope is global */
713                 }
714               else
715                 /* symbol is local */
716                 fprintf (afile, "L%s_",
717                          (sym->localof ? sym->localof->name : "-null-"));
718               fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
719             }
720
721           /* if is has an absolute address then generate
722              an equate for this no need to allocate space */
723           if (SPEC_ABSA (sym->etype))
724             {
725
726               if (options.debug || sym->level == 0)
727                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
728
729               fprintf (afile, "%s\t=\t0x%04x\n",
730                        sym->rname,
731                        SPEC_ADDR (sym->etype));
732             }
733           else
734             {
735               if (options.debug || sym->level == 0)
736                 fprintf (afile, "==.\n");
737
738               /* allocate space */
739               fprintf (afile, "%s:\n", sym->rname);
740               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
741             }
742
743         }
744     }
745 }
746
747
748 /*-----------------------------------------------------------------*/
749 /* glue - the final glue that hold the whole thing together        */
750 /*-----------------------------------------------------------------*/
751 void
752 picglue ()
753 {
754
755   FILE *vFile;
756   FILE *asmFile;
757   FILE *ovrFile = tempfile();
758
759   addSetHead(&tmpfileSet,ovrFile);
760   pCodeInitRegisters();
761
762   if (mainf && IFFUNC_HASBODY(mainf->type)) {
763
764     pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
765     addpBlock(pb);
766
767     /* entry point @ start of CSEG */
768     addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
769     /* put in the call to main */
770     addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
771
772     if (options.mainreturn) {
773
774       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
775       addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
776
777     } else {
778
779       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
780       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
781
782     }
783   }
784
785
786   /* At this point we've got all the code in the form of pCode structures */
787   /* Now it needs to be rearranged into the order it should be placed in the */
788   /* code space */
789
790   movepBlock2Head('P');              // Last
791   movepBlock2Head(code->dbName);
792   movepBlock2Head('X');
793   movepBlock2Head(statsg->dbName);   // First
794
795
796   /* print the global struct definitions */
797   if (options.debug)
798     cdbStructBlock (0);
799
800   vFile = tempfile();
801
802   addSetHead(&tmpfileSet,vFile);
803     
804   /* emit code for the all the variables declared */
805   pic14emitMaps ();
806   /* do the overlay segments */
807   pic14emitOverlay(ovrFile);
808
809   /* PENDING: this isnt the best place but it will do */
810   if (port->general.glue_up_main) {
811     /* create the interrupt vector table */
812     pic14createInterruptVect (vFile);
813   }
814
815   AnalyzepCode('*');
816
817   //#ifdef PCODE_DEBUG
818   //printCallTree(stderr);
819   //#endif
820
821   InlinepCode();
822
823   AnalyzepCode('*');
824
825   pcode_test();
826
827
828   /* now put it all together into the assembler file */
829   /* create the assembler file name */
830     
831   if ((noAssemble || options.c1mode) && fullDstFileName)
832     {
833       sprintf (buffer, fullDstFileName);
834     }
835   else
836     {
837       sprintf (buffer, dstFileName);
838       strcat (buffer, ".asm");
839     }
840
841   if (!(asmFile = fopen (buffer, "w"))) {
842     werror (E_FILE_OPEN_ERR, buffer);
843     exit (1);
844   }
845     
846   /* initial comments */
847   pic14initialComments (asmFile);
848     
849   /* print module name */
850   fprintf (asmFile, ";\t.module %s\n", moduleName);
851     
852   /* Let the port generate any global directives, etc. */
853   if (port->genAssemblerPreamble)
854     {
855       port->genAssemblerPreamble(asmFile);
856     }
857     
858   /* print the extern variables in this module */
859   pic14printExterns (asmFile);
860
861   /* print the global variables in this module */
862   pic14printPublics (asmFile);
863
864   /* copy the sfr segment */
865   fprintf (asmFile, "%s", iComments2);
866   fprintf (asmFile, "; special function registers\n");
867   fprintf (asmFile, "%s", iComments2);
868   copyFile (asmFile, sfr->oFile);
869
870   fprintf (asmFile, "%s", iComments2);
871   fprintf (asmFile, "; %s\n", udata_section_name);
872   fprintf (asmFile, "%s", iComments2);
873   fprintf (asmFile, "\t%s\n", udata_section_name);
874   copyFile (asmFile, data->oFile);
875
876   /* Put all variables into a cblock */
877   AnalyzeBanking();
878   writeUsedRegs(asmFile);
879
880   /* create the overlay segments */
881   fprintf (asmFile, "%s", iComments2);
882   fprintf (asmFile, "; overlayable items in internal ram \n");
883   fprintf (asmFile, "%s", iComments2);    
884   copyFile (asmFile, ovrFile);
885
886 #if 0
887
888   /* create the stack segment MOF */
889   if (mainf && IFFUNC_HASBODY(mainf->type)) {
890     fprintf (asmFile, "%s", iComments2);
891     fprintf (asmFile, "; Stack segment in internal ram \n");
892     fprintf (asmFile, "%s", iComments2);    
893     fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
894              ";__start__stack:\n;\t.ds\t1\n\n");
895   }
896
897   /* create the idata segment */
898   fprintf (asmFile, "%s", iComments2);
899   fprintf (asmFile, "; indirectly addressable internal ram data\n");
900   fprintf (asmFile, "%s", iComments2);
901   copyFile (asmFile, idata->oFile);
902     
903   /* if external stack then reserve space of it */
904   if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
905     fprintf (asmFile, "%s", iComments2);
906     fprintf (asmFile, "; external stack \n");
907     fprintf (asmFile, "%s", iComments2);
908     fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
909     fprintf (asmFile,";\t.ds 256\n");
910   }
911
912   /* copy xtern ram data */
913   fprintf (asmFile, "%s", iComments2);
914   fprintf (asmFile, "; external ram data\n");
915   fprintf (asmFile, "%s", iComments2);
916   copyFile (asmFile, xdata->oFile);
917
918 #endif
919
920   /* copy the bit segment */
921   fprintf (asmFile, "%s", iComments2);
922   fprintf (asmFile, "; bit data\n");
923   fprintf (asmFile, "%s", iComments2);
924   copyFile (asmFile, bit->oFile);
925
926   /* copy the interrupt vector table */
927   if (mainf && IFFUNC_HASBODY(mainf->type)) {
928     copyFile (asmFile, vFile);
929     
930     fprintf (asmFile, "%s", iComments2);
931     fprintf (asmFile, "; interrupt and initialization code\n");
932     fprintf (asmFile, "%s", iComments2);
933     fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME);
934
935     /* interrupt service routine */
936     fprintf (asmFile, "__sdcc_interrupt:\n");
937     copypCode(asmFile, 'I');
938
939     /* initialize data memory */
940     fprintf (asmFile,"__sdcc_gsinit_startup:\n");
941     /* FIXME: This is temporary.  The idata section should be used.  If 
942        not, we could add a special feature to the linker.  This will 
943        work in the mean time.  Put all initalized data in main.c */
944     copypCode(asmFile, statsg->dbName);
945     fprintf (asmFile,"\tpagesel _main\n");
946     fprintf (asmFile,"\tgoto _main\n");
947   }
948
949 #if 0    
950
951   /* copy global & static initialisations */
952   fprintf (asmFile, "%s", iComments2);
953   fprintf (asmFile, "; global & static initialisations\n");
954   fprintf (asmFile, "%s", iComments2);
955   copypCode(asmFile, statsg->dbName);
956
957 #endif
958
959   /* copy over code */
960   fprintf (asmFile, "%s", iComments2);
961   fprintf (asmFile, "; code\n");
962   fprintf (asmFile, "%s", iComments2);
963   fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
964
965   /* unknown */
966   copypCode(asmFile, 'X');
967   
968   /* _main function */
969   copypCode(asmFile, 'M');
970
971   /* other functions */
972   copypCode(asmFile, code->dbName);
973
974   /* unknown */
975   copypCode(asmFile, 'P');
976
977   fprintf (asmFile,"\tend\n");
978
979   fclose (asmFile);
980
981   rm_tmpfiles();
982 }