PIC Port - fixed pointer/array accesses. Stream line comparisons. Started function...
[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
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('*');
817
818   //#ifdef PCODE_DEBUG
819   //printCallTree(stderr);
820   //#endif
821 /*
822   InlinepCode();
823
824   AnalyzepCode('*');
825 */
826   pcode_test();
827
828
829   /* now put it all together into the assembler file */
830   /* create the assembler file name */
831     
832   if (!options.c1mode) {
833     sprintf (buffer, srcFileName);
834     strcat (buffer, ".asm");
835   }
836   else {
837     strcpy(buffer, options.out_name);
838   }
839
840   if (!(asmFile = fopen (buffer, "w"))) {
841     werror (E_FILE_OPEN_ERR, buffer);
842     exit (1);
843   }
844     
845   /* initial comments */
846   pic14initialComments (asmFile);
847     
848   /* print module name */
849   fprintf (asmFile, ";\t.module %s\n", moduleName);
850     
851   /* Let the port generate any global directives, etc. */
852   if (port->genAssemblerPreamble)
853     {
854       port->genAssemblerPreamble(asmFile);
855     }
856     
857   /* print the global variables in this module */
858   pic14printPublics (asmFile);
859     
860
861   /* copy the sfr segment */
862   fprintf (asmFile, "%s", iComments2);
863   fprintf (asmFile, "; special function registers\n");
864   fprintf (asmFile, "%s", iComments2);
865   copyFile (asmFile, sfr->oFile);
866     
867
868   /* Put all variables into a cblock */
869   writeUsedRegs(asmFile);
870   AnalyzeBanking();
871
872   /* create the overlay segments */
873   fprintf (asmFile, "%s", iComments2);
874   fprintf (asmFile, "; overlayable items in internal ram \n");
875   fprintf (asmFile, "%s", iComments2);    
876   copyFile (asmFile, ovrFile);
877
878   /* create the stack segment MOF */
879   if (mainf && IFFUNC_HASBODY(mainf->type)) {
880     fprintf (asmFile, "%s", iComments2);
881     fprintf (asmFile, "; Stack segment in internal ram \n");
882     fprintf (asmFile, "%s", iComments2);    
883     fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
884              ";__start__stack:\n;\t.ds\t1\n\n");
885   }
886
887   /* create the idata segment */
888   fprintf (asmFile, "%s", iComments2);
889   fprintf (asmFile, "; indirectly addressable internal ram data\n");
890   fprintf (asmFile, "%s", iComments2);
891   copyFile (asmFile, idata->oFile);
892     
893   /* if external stack then reserve space of it */
894   if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
895     fprintf (asmFile, "%s", iComments2);
896     fprintf (asmFile, "; external stack \n");
897     fprintf (asmFile, "%s", iComments2);
898     fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
899     fprintf (asmFile,";\t.ds 256\n");
900   }
901         
902         
903   /* copy xtern ram data */
904   fprintf (asmFile, "%s", iComments2);
905   fprintf (asmFile, "; external ram data\n");
906   fprintf (asmFile, "%s", iComments2);
907   copyFile (asmFile, xdata->oFile);
908     
909
910   /* copy the bit segment */
911   fprintf (asmFile, "%s", iComments2);
912   fprintf (asmFile, "; bit data\n");
913   fprintf (asmFile, "%s", iComments2);
914   copyFile (asmFile, bit->oFile);
915
916
917   fprintf (asmFile, "\tORG 0\n");
918
919   /* copy the interrupt vector table */
920   if (mainf && IFFUNC_HASBODY(mainf->type)) {
921     fprintf (asmFile, "%s", iComments2);
922     fprintf (asmFile, "; interrupt vector \n");
923     fprintf (asmFile, "%s", iComments2);
924     copyFile (asmFile, vFile);
925   }
926     
927   /* copy global & static initialisations */
928   fprintf (asmFile, "%s", iComments2);
929   fprintf (asmFile, "; global & static initialisations\n");
930   fprintf (asmFile, "%s", iComments2);
931     
932   /* Everywhere we generate a reference to the static_name area, 
933    * (which is currently only here), we immediately follow it with a 
934    * definition of the post_static_name area. This guarantees that
935    * the post_static_name area will immediately follow the static_name
936    * area.
937    */
938   fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
939   fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
940   fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
941     
942   if (mainf && IFFUNC_HASBODY(mainf->type)) {
943     fprintf (asmFile,"__sdcc_gsinit_startup:\n");
944     /* if external stack is specified then the
945        higher order byte of the xdatalocation is
946        going into P2 and the lower order going into
947        spx */
948     if (options.useXstack) {
949       fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
950               (((unsigned int)options.xdata_loc) >> 8) & 0xff);
951       fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
952               (unsigned int)options.xdata_loc & 0xff);
953     }
954
955   }
956
957   if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
958     {
959       /* This code is generated in the post-static area.
960        * This area is guaranteed to follow the static area
961        * by the ugly shucking and jiving about 20 lines ago.
962        */
963       fprintf(asmFile, ";\t.area %s\n", port->mem.post_static_name);
964       fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
965     }
966         
967   /* copy over code */
968   fprintf (asmFile, "%s", iComments2);
969   fprintf (asmFile, "; code\n");
970   fprintf (asmFile, "%s", iComments2);
971   fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
972
973   //copyFile (stderr, code->oFile);
974
975   copypCode(asmFile, 'I');
976   copypCode(asmFile, statsg->dbName);
977   copypCode(asmFile, 'X');
978   copypCode(asmFile, 'M');
979   copypCode(asmFile, code->dbName);
980   copypCode(asmFile, 'P');
981
982
983   fprintf (asmFile,"\tend\n");
984
985   fclose (asmFile);
986   applyToSet(tmpfileSet,closeTmpFiles);
987   applyToSet(tmpfileNameSet, rmTmpFiles);
988 }