introduced atexit() handler for teporay files removal in case of errors, assertions...
[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 extern void InlinepCode(void);
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 void  pCodeInitRegisters(void);
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
738   addSetHead(&tmpfileSet,ovrFile);
739   pCodeInitRegisters();
740
741   if (mainf && IFFUNC_HASBODY(mainf->type)) {
742
743     pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
744     addpBlock(pb);
745
746     /* entry point @ start of CSEG */
747     addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
748     /* put in the call to main */
749     addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
750
751     if (options.mainreturn) {
752
753       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
754       addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
755
756     } else {
757
758       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
759       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
760
761     }
762   }
763
764
765   /* At this point we've got all the code in the form of pCode structures */
766   /* Now it needs to be rearranged into the order it should be placed in the */
767   /* code space */
768
769   movepBlock2Head('P');              // Last
770   movepBlock2Head(code->dbName);
771   movepBlock2Head('X');
772   movepBlock2Head(statsg->dbName);   // First
773
774
775   /* print the global struct definitions */
776   if (options.debug)
777     cdbStructBlock (0,cdbFile);
778
779   vFile = tempfile();
780   /* PENDING: this isnt the best place but it will do */
781   if (port->general.glue_up_main) {
782     /* create the interrupt vector table */
783     pic14createInterruptVect (vFile);
784   }
785
786   addSetHead(&tmpfileSet,vFile);
787     
788   /* emit code for the all the variables declared */
789   pic14emitMaps ();
790   /* do the overlay segments */
791   pic14emitOverlay(ovrFile);
792
793
794   AnalyzepCode('*');
795
796   //#ifdef PCODE_DEBUG
797   //printCallTree(stderr);
798   //#endif
799
800   InlinepCode();
801
802   AnalyzepCode('*');
803
804   pcode_test();
805
806
807   /* now put it all together into the assembler file */
808   /* create the assembler file name */
809     
810   if (!options.c1mode) {
811     sprintf (buffer, srcFileName);
812     strcat (buffer, ".asm");
813   }
814   else {
815     strcpy(buffer, options.out_name);
816   }
817
818   if (!(asmFile = fopen (buffer, "w"))) {
819     werror (E_FILE_OPEN_ERR, buffer);
820     exit (1);
821   }
822     
823   /* initial comments */
824   pic14initialComments (asmFile);
825     
826   /* print module name */
827   fprintf (asmFile, ";\t.module %s\n", moduleName);
828     
829   /* Let the port generate any global directives, etc. */
830   if (port->genAssemblerPreamble)
831     {
832       port->genAssemblerPreamble(asmFile);
833     }
834     
835   /* print the global variables in this module */
836   pic14printPublics (asmFile);
837     
838
839   /* copy the sfr segment */
840   fprintf (asmFile, "%s", iComments2);
841   fprintf (asmFile, "; special function registers\n");
842   fprintf (asmFile, "%s", iComments2);
843   copyFile (asmFile, sfr->oFile);
844     
845
846   /* Put all variables into a cblock */
847   AnalyzeBanking();
848   writeUsedRegs(asmFile);
849
850   /* create the overlay segments */
851   fprintf (asmFile, "%s", iComments2);
852   fprintf (asmFile, "; overlayable items in internal ram \n");
853   fprintf (asmFile, "%s", iComments2);    
854   copyFile (asmFile, ovrFile);
855
856   /* create the stack segment MOF */
857   if (mainf && IFFUNC_HASBODY(mainf->type)) {
858     fprintf (asmFile, "%s", iComments2);
859     fprintf (asmFile, "; Stack segment in internal ram \n");
860     fprintf (asmFile, "%s", iComments2);    
861     fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
862              ";__start__stack:\n;\t.ds\t1\n\n");
863   }
864
865   /* create the idata segment */
866   fprintf (asmFile, "%s", iComments2);
867   fprintf (asmFile, "; indirectly addressable internal ram data\n");
868   fprintf (asmFile, "%s", iComments2);
869   copyFile (asmFile, idata->oFile);
870     
871   /* if external stack then reserve space of it */
872   if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
873     fprintf (asmFile, "%s", iComments2);
874     fprintf (asmFile, "; external stack \n");
875     fprintf (asmFile, "%s", iComments2);
876     fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
877     fprintf (asmFile,";\t.ds 256\n");
878   }
879         
880         
881   /* copy xtern ram data */
882   fprintf (asmFile, "%s", iComments2);
883   fprintf (asmFile, "; external ram data\n");
884   fprintf (asmFile, "%s", iComments2);
885   copyFile (asmFile, xdata->oFile);
886     
887
888   /* copy the bit segment */
889   fprintf (asmFile, "%s", iComments2);
890   fprintf (asmFile, "; bit data\n");
891   fprintf (asmFile, "%s", iComments2);
892   copyFile (asmFile, bit->oFile);
893
894
895   fprintf (asmFile, "\tORG 0\n");
896
897   /* copy the interrupt vector table */
898   if (mainf && IFFUNC_HASBODY(mainf->type)) {
899     fprintf (asmFile, "%s", iComments2);
900     fprintf (asmFile, "; interrupt vector \n");
901     fprintf (asmFile, "%s", iComments2);
902     copyFile (asmFile, vFile);
903   }
904     
905   /* copy global & static initialisations */
906   fprintf (asmFile, "%s", iComments2);
907   fprintf (asmFile, "; global & static initialisations\n");
908   fprintf (asmFile, "%s", iComments2);
909     
910   /* Everywhere we generate a reference to the static_name area, 
911    * (which is currently only here), we immediately follow it with a 
912    * definition of the post_static_name area. This guarantees that
913    * the post_static_name area will immediately follow the static_name
914    * area.
915    */
916   fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
917   fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
918   fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
919     
920   if (mainf && IFFUNC_HASBODY(mainf->type)) {
921     fprintf (asmFile,"__sdcc_gsinit_startup:\n");
922     /* if external stack is specified then the
923        higher order byte of the xdatalocation is
924        going into P2 and the lower order going into
925        spx */
926     if (options.useXstack) {
927       fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
928               (((unsigned int)options.xdata_loc) >> 8) & 0xff);
929       fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
930               (unsigned int)options.xdata_loc & 0xff);
931     }
932
933   }
934
935   if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
936     {
937       /* This code is generated in the post-static area.
938        * This area is guaranteed to follow the static area
939        * by the ugly shucking and jiving about 20 lines ago.
940        */
941       fprintf(asmFile, ";\t.area %s\n", port->mem.post_static_name);
942       fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
943     }
944         
945   /* copy over code */
946   fprintf (asmFile, "%s", iComments2);
947   fprintf (asmFile, "; code\n");
948   fprintf (asmFile, "%s", iComments2);
949   fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
950
951   //copyFile (stderr, code->oFile);
952
953   copypCode(asmFile, 'I');
954   copypCode(asmFile, statsg->dbName);
955   copypCode(asmFile, 'X');
956   copypCode(asmFile, 'M');
957   copypCode(asmFile, code->dbName);
958   copypCode(asmFile, 'P');
959
960
961   fprintf (asmFile,"\tend\n");
962
963   fclose (asmFile);
964
965   rm_tmpfiles();
966 }