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