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