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